Skip to content

Commit 6e8097f

Browse files
author
Kapil Borle
committed
Modify PSModulePath in module dependency handler
Adds a temporary path to the PSModulePath that contains the downloaded modules. This prevents the powershell parser from throwing parse errors when it cannot find a symbol that refers to an external module.
1 parent e81cc3b commit 6e8097f

File tree

1 file changed

+21
-60
lines changed

1 file changed

+21
-60
lines changed

Engine/Generic/ModuleDependencyHandler.cs

Lines changed: 21 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,27 @@
66
using System.Management.Automation;
77
using System.Management.Automation.Language;
88
using System.Management.Automation.Runspaces;
9-
using System.Text;
109

1110
namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic
1211
{
1312
// TODO Use runspace pool
1413
// TODO Create a new process for the runspace
15-
// TODO Support for verbose mode
16-
// TODO Try changing the psmodulepath variable through powershell layer. This will save copying and removing the modules
14+
// TODO Support for verbose mode
1715
public class ModuleDependencyHandler : IDisposable
1816
{
1917
#region Private Variables
2018
private Runspace runspace;
2119
private readonly string moduleRepository;
22-
private string tempDirPath;
23-
private string localPSModulePath;
20+
private string tempDirPath;
2421
Dictionary<string, PSObject> modulesFound;
25-
HashSet<string> modulesSavedInModulePath;
2622
HashSet<string> modulesSavedInTempPath;
2723
private string localAppdataPath;
2824
private string pssaAppdataPath;
2925
private const string symLinkName = "TempModuleDir";
3026
private const string tempPrefix = "PSSAModules-";
3127
private string symLinkPath;
28+
private string oldPSModulePath;
29+
private string curPSModulePath;
3230

3331
#endregion Private Variables
3432

@@ -144,20 +142,13 @@ private string GetTempDirPath(string symLinkPath)
144142
private void CleanUp()
145143
{
146144
runspace.Dispose();
147-
148-
// remove the modules from local psmodule path
149-
foreach (var dir in Directory.EnumerateDirectories(localPSModulePath))
150-
{
151-
if (IsModuleNamePresent(modulesSavedInModulePath, Path.GetFileName(dir)))
152-
{
153-
Directory.Delete(dir, true);
154-
}
155-
}
145+
RestorePSModulePath();
156146
}
157147

158148
private void SaveModule(PSObject module)
159149
{
160150
ThrowIfNull(module, "module");
151+
161152
// TODO validate module
162153
var ps = System.Management.Automation.PowerShell.Create();
163154
ps.Runspace = runspace;
@@ -166,19 +157,6 @@ private void SaveModule(PSObject module)
166157
.AddParameter("InputObject", module);
167158
ps.Invoke();
168159
}
169-
170-
// TODO Use powershell copy-item
171-
private void CopyDir(string srcPath, string dstPath)
172-
{
173-
var ps = System.Management.Automation.PowerShell.Create();
174-
ps.Runspace = runspace;
175-
ps.AddCommand("Copy-Item")
176-
.AddParameter("Recurse")
177-
.AddParameter("Path", srcPath)
178-
.AddParameter("Destination", dstPath);
179-
ps.Invoke();
180-
}
181-
182160
#endregion Private Methods
183161

184162
#region Public Methods
@@ -187,21 +165,27 @@ public ModuleDependencyHandler()
187165
{
188166
runspace = null;
189167
moduleRepository = "PSGallery";
190-
modulesSavedInModulePath = new HashSet<string>();
191168
modulesSavedInTempPath = new HashSet<string>();
192-
modulesFound = new Dictionary<string, PSObject>();
193-
194-
// TODO search it in the $psmodulepath instead of constructing it
195-
localPSModulePath = Path.Combine(
196-
Environment.GetEnvironmentVariable("USERPROFILE"),
197-
"Documents\\WindowsPowerShell\\Modules");
169+
modulesFound = new Dictionary<string, PSObject>();
198170
localAppdataPath = Environment.GetEnvironmentVariable("LOCALAPPDATA");
199171

200172
// TODO Add PSSA Version in the path
201173
pssaAppdataPath = Path.Combine(localAppdataPath, "PSScriptAnalyzer");
202174
symLinkPath = Path.Combine(pssaAppdataPath, symLinkName);
203-
204175
SetupCache();
176+
SetupPSModulePath();
177+
}
178+
179+
private void SetupPSModulePath()
180+
{
181+
oldPSModulePath = Environment.GetEnvironmentVariable("PSModulePath");
182+
curPSModulePath = oldPSModulePath + ";" + tempDirPath;
183+
Environment.SetEnvironmentVariable("PSModulePath", curPSModulePath, EnvironmentVariableTarget.Process);
184+
}
185+
186+
private void RestorePSModulePath()
187+
{
188+
Environment.SetEnvironmentVariable("PSModulePath", oldPSModulePath, EnvironmentVariableTarget.Process);
205189
}
206190

207191
public ModuleDependencyHandler(Runspace runspace) : this()
@@ -267,14 +251,8 @@ public bool ModuleExists(string moduleName)
267251
public void SaveModule(string moduleName)
268252
{
269253
ThrowIfNull(moduleName, "moduleName");
270-
if (IsModuleNamePresent(modulesSavedInModulePath, moduleName))
271-
{
272-
return;
273-
}
274254
if (IsModuleNamePresent(modulesSavedInTempPath, moduleName))
275-
{
276-
// copy to local ps module path
277-
CopyToPSModulePath(moduleName);
255+
{
278256
return;
279257
}
280258

@@ -289,25 +267,8 @@ public void SaveModule(string moduleName)
289267
}
290268
SaveModule(module);
291269
AddModuleName(modulesSavedInTempPath, moduleName);
292-
CopyToPSModulePath(moduleName);
293270
}
294271

295-
private void CopyToPSModulePath(string moduleName, bool checkModulePresence = false)
296-
{
297-
if (checkModulePresence)
298-
{
299-
foreach(var dir in Directory.EnumerateDirectories(localPSModulePath))
300-
{
301-
if (Path.GetFileName(dir).Equals(moduleName, StringComparison.OrdinalIgnoreCase))
302-
{
303-
return;
304-
}
305-
}
306-
}
307-
CopyDir(Path.Combine(tempDirPath, moduleName), localPSModulePath);
308-
AddModuleName(modulesSavedInModulePath, moduleName);
309-
}
310-
311272
public static string GetModuleNameFromErrorExtent(ParseError error, ScriptBlockAst ast)
312273
{
313274
ThrowIfNull(error, "error");

0 commit comments

Comments
 (0)