Check if Powershell Module is installed in C# - c#

Is it possible to check if a powershell module ist installed in C#?
I need a C# condition if a module is / or is not installed.
I know how to use powershell in C#, but how become a response from Powershell?
Thanks for reading my question and i hope anyone can give me some hints.

You can add a reference to System.Management.Automation and use the PowerShell to invoke Get-Module cmdlet to check if a specific module has been installed:
var exists = false;
using (PowerShell ps = PowerShell.Create())
{
string moduleName = "something";
ps.AddScript($"Get-Module -ListAvailable -Name {moduleName}");
var result = ps.Invoke();
exists = result.Count > 0;
}
Note: To add a reference to System.Management.Automation, you can install the NuGet package using Install-Package System.Management.Automation.dll Or if you want to see where the dll is located on your system, using powershell console, you can see [PSObject].Assembly.Location and pick it.

Related

Invoking Powershell file blocks referenced Libraries

I am executing a Powershell script file from C# with the following code:
Runspace _rs = RunspaceFactory.CreateRunspace();
_rs.ApartmentState = ApartmentState.STA;
_rs.Open();
PipeLine _pipeLine = _rs.CreatePipeline();
Command scriptCommand = new Command(filePath);
_pipeLine.Invoke();
In the powershell script file I am referencing libraries:
Add-Type -Path Filepath.dll
In C# i am disposing the runspace and pipeline afterwords trying to unlock the associated libraries.
finally
{
_rs.Dispose();
_pipeLine.Dispose();
}
Unfortunately in a later step when trying to delete the dll files associated in the script, i get a UnauthorizedException. Please note that i dont get the exception if i never run the script from C#. I def should have accss to it.

c# Visual Studio 2015 - how to create a Setup which uninstall other application

Initially I created an application that I completely rewrite in a second version. It is a complete different Visual studio solution.
Now I would like that its Setup installer uninstall the previous version but because it was not created using the same solution, the automatic uninstallation of previous version does not work.
Is there any way to force the installer to uninstall certain application based on product name or product code?
I found a WMIC command that works when run from command line
wmic product where name="XXXX" call uninstall /nointeractive
So I created a VBS script which execute a bat file containing the WMIC code and I added it to the Setup project
dim shell
set shell=createobject("wscript.shell")
shell.run "uninstallAll.bat",0,true
set shell=nothing
but when I run the result MSI, it fires an error 1001, meaning that a service already exists. , in other words the uninstallation didn't work.
The old program is still present and they create a service with the same name. :/
any suggestion?
There are 2 options:
You can increase the version of MSI project so it will treat as upgrade and it will not throw any error while installing.
another way out is the write some in the installer project as follows:
protected override void OnBeforeInstall(IDictionary savedState)
{
//Write uninstall powershell script
//installutil /u <yourproject>.exe
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript("");
PowerShellInstance.AddParameter("");
}
PowerShellInstance.Invoke();
}
Note: This InstallUtil is available with the .NET Framework, and its path is %WINDIR%\Microsoft.NET\Framework[64]\<framework_version>.
For example, for the 32-bit version of the .NET Framework 4 or 4.5.*, if your Windows installation directory is C:\Windows, the path is C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe.
For the 64-bit version of the .NET Framework 4 or 4.5.*, the default path is C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe
I decided to go for the option of introducing c# code in the project installer. Firstly I added the reference for System.Management.Automation via nuget
https://www.nuget.org/packages/System.Management.Automation
After this, I just created a string variable containing the PS code I need to uninstall several programs with a similar name.
string unInstallKiosk = #"$app = get-WMIObject win32_Product -Filter ""name like 'KIOSK'""
foreach ($program in $app){
$app2 = Get-WmiObject -Class Win32_Product | Where -Object { $_.IdentifyingNumber -match ""$($program.identifyingNumber)""
}
$app2.Uninstall()}";
and passed this variable to the method PowerShellInstance.AddScript()
PowerShellInstance.AddScript(unInstallKiosk);
The installation ends but the uninstallation simply dont happens.
anyone has an idea how to solve this?

Invoke Powershell Command from .net framework 2.0 / 3.5 project

I'm trying to invoke a Powershell Command Get-DSCLocalConfigurationManager from a windows service project (.net framework 2.0). using System.Management.Automation
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
try
{
runspace.Open();
var ps = PowerShell.Create();
ps.Runspace = runspace;
ps.AddCommand("Get-DSCLocalConfigurationManager");
var results = ps.Invoke();
foreach (PSObject result in ps.Invoke())
{
_eventLog.WriteEntry(result.Members["AgentId"].Value.ToString());
}
}
catch (Exception e)
{
_eventLog.WriteEntry($"Powershell Command failed with: {e.Message}", EventLogEntryType.Error);
}
}
Invoking the command in a powershell window works as expected.
The problem is that pretty much every command i try to invoke this way returns an exception:
"The term 'Get-DSCLocalConfigurationManager' is not recognized as the name of a cmdlet,..."
I tried the commands Get-Module -ListAvailable $PSVersionTable.PSVersion with the same result. There are commands that work like Get-Process, so i assume there are missing modules.
Importing the module and invoking the command like this
ps.AddScript(#"Import -Module 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psd1'; Get-DSCLocalConfigurationManager");
also doesn't work as it returns the following error:
The 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psd1' module cannot be imported because its manifest contains one or more members that are not valid. The valid manifest members are ('ModuleToProcess', 'NestedModules', 'GUID', 'Author', 'CompanyName', 'Copyright', 'ModuleVersion', 'Description', 'PowerShellVersion', 'PowerShellHostName', 'PowerShellHostVersion', 'CLRVersion', 'DotNetFrameworkVersion', 'ProcessorArchitecture', 'RequiredModules', 'TypesToProcess', 'FormatsToProcess', 'ScriptsToProcess', 'PrivateData', 'RequiredAssemblies', 'ModuleList', 'FileList', 'FunctionsToExport', 'VariablesToExport', 'AliasesToExport', 'CmdletsToExport'). Remove the members that are not valid ('DscResourcesToExport', 'HelpInfoURI'), then try to import the module again.
What Powershell version is used when invoking commands like this? Is it tied to the .net framework version I'm using or is it the installed version of the system? What Modules are loaded? What can i do to invoke this command?
Edit: I created a simple console application and found out, that this is connected with the framework version. With .net framework 4.0 this works as expected, but as soon as i use 3.5 or lower the problem i describe arises.
I had same problem.
It comes from version of Powershell.
When you target project to .Net 2.0/3.5 you using System.Management.Automation.dll version 1.0.0.0, that runs Powershell 2.0, but when your project targets to .Net 4+, using dll version 3.0.0.0 and runs Powershell 3.0.
I pass to my runtime Powershell command to call shell Powershell and execute command, like this:
var results = powerShell.AddScript("powershell Get-AppxPackage -allusers -name 'Microsoft.WindowsStore'").Invoke();
if (powerShell.Streams.Error.Any())
{
foreach (var errorRecord in powerShell.Streams.Error)
throw new Exception();
}
Called Ppowershell redirects streams to runtime Powershell.

Error while Trying to load Powershell Module "MSOnline" in ASP.NET web app

Good morning I have one problem trying o load a Powershell Module called MSOnline in a ASP.NET
After following this links:
http://www.msdigest.net/2012/03/how-to-connect-to-office-365-with-powershell/
http://blogs.technet.com/b/educloud/archive/2013/01/23/managing-office-365-for-education-using-powershell.aspx
This is a Button that run a script via Code Behind in C#. When I was trying to load the module it threw an exception.
protected void Bexecute_Click(object sender, EventArgs e)
{
// Import-Module MSOnline
try
{
//Loading MSOnline using a InitialSessionState
InitialSessionState iss = InitialSessionState.CreateDefault();
iss.ImportPSModule(new string[] { "MSOnline" });
//Before the solution iss has an exception of "not found" the MSOnline Module
//Create a runspace
Runspace test = RunspaceFactory.CreateRunspace(iss);
//Open a Runspace
test.Open();
//Create a Pipeline
Pipeline pipeLine = test.CreatePipeline();
//Create the StringBuilder to get append the script
StringBuilder script = new StringBuilder();
//Take the script from Tscript (TextBoxt with ID="Tscript" in default.aspx
script.AppendLine(#"Get-Module -ListAvailable");
//Add the script and commands to the pipeline;
pipeLine.Commands.AddScript(script.ToString());
//Execute script and get the PSObject Results collection
Collection<PSObject> resultObjects = pipeLine.Invoke();
//Close the Runspace
test.Close();
if (resultObjects.Count > 0)
{
/*** DO SOMETHING WITH THE PSObjects ***/
}
}
catch (System.Management.Automation.RuntimeException ex)
{
status.AppendLine(ex.Message);
}
}
What I need is what could be wrong. I referenced the system.management.automation (dll). But I don't have a clue why is not listed if it's installed it. Thank you for the help.
I have found MSOnline .dll files in : C:\windows\system32\WindowsPowerShell\v1.0\Modules\MSOnline
But If I tried to add manually from visual studio it says "that MSOnline doesn't exist".
This is quite weird, because all have same permissions to folder. What's going on! :S This is so frustrating...
To get ASP.NET web app run under x64 bit architecture you should do this:
1, MS Online Services Assistant needs to be downloaded and installed
Microsoft Online Services Sign-In Assistant – 64 bit version http://go.microsoft.com/fwlink/?linkid=236300
2.MS Online Module for PowerShell needs to be downloaded and installed
Microsoft Online Services Module for Windows PowerShell (64-bit version) http://go.microsoft.com/fwlink/?linkid=236297
After this step you can run: get-module -ListAvailable and the Module MSOnline will be listed.
But it is still not working on 64 bits SOs. the original poster used win8 64bits and I am using win 8.1 64 bits and it works as well.
Copy the MSOnline module folder from (Path1) to (Path2) where
(Path1) -> "C:\Windows\System32\WindowsPowerShell\v1.0\Modules\MSOnline" and
(Path2) -> "C:\Windows\SysWOW64\WindowsPowerShell\v1.0\Modules\MSOnline"
Considering I'm running this on VS2013 under Windows 8.1 and 64 bits arquitecture.
After doing this the MSOnline Module is listed in the Get-Module -ListAvailable (from webapp, not just for powershell)), so I could import it and use it.

The term 'connect-QADService' is not recognized as the name of a cmdlet... inside C# function

Can someone, please, help to understand why the following code inside a Csharp function
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipe = runspace.CreatePipeline();
Command connectToActDir = new Command("connect-QADService");
connectToActDir.Parameters.Add("Service", "'ip:port'");
connectToActDir.Parameters.Add("ConnectionAccount", "'user.local\administrator'");
connectToActDir.Parameters.Add("ConnectionPassword", "'password'");
pipe.Commands.Add(connectToActDir);
pipe.Invoke();
causes the following error
The term 'connect-QADService' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
while ActiveRoles cmdlets are installed and running the equivalent command in power shell succeeds. Do I miss some dll in project references?
Thanks
The Quest ActiveRoles cmdlets are not loaded into a PowerShell session by default, because they're not part of PowerShell.
PowerShell 3 will automatically load modules when needed. I don't know if this holds true when using a RunSpace as I've never used PowerShell this way.
Do you load the Quest snap-in or module in your PowerShell profile? You'll need to do the equivalent in your C# code.

Categories