I am trying to execute a Powershell script remotely that will launch an accdb file via MSAccess. I am able to get the Powershell script to execute successfully, but MSAccess is not launching since I know that the test.accdb file that I have is not getting updated. What am I missing in my code in order to be able to launch MSAccess? Or is it not possible?
My code is running in a Windows 2012 R2 environment in IIS and is being executed by a service account that has Admin privileges to the machine. If I run the code logged in as that service account, it works fine without issues. If I execute it remotely, only part of the code is executed
My code for the .NET app is as follows (running under service account). I've changed some of the private information, but it doesn't effect the code.
internal static HttpStatusCode ExecuteRemoteCommand()
{
WSManConnectionInfo connectioninfo = new WSManConnectionInfo();
connectioninfo.ComputerName = "testcomputer";
using (Runspace runspace = RunspaceFactory.CreateRunspace(connectioninfo))
{
runspace.Open();
using (PowerShell ps = PowerShell.Create())
{
ps.Runspace = runspace;
var re = ps.AddScript(#"\\testcomputer\test\StartTest.ps1");
var results = re.Invoke();
}
}
return HttpStatusCode.Created;
}
My Powershell code is as follows:
try {
$msAccess = "C:\Program Files (x86)\Microsoft Office\Office14\msaccess.exe"
$fileLocation = "C:\test\DBT.accdb"
Start-Process -FilePath $msAccess -ArgumentList $fileLocation -Verb RunAs -WindowStyle Hidden -WorkingDirectory "C:\test"
$today = Get-Date
"SUCCESS: " + $today > "c:\test\TestExecutionSuccess.txt"
}
Catch
{
$_.Exception.Message > "c:\test\TestExecutionError.txt"
}
In both cases, the one where I run the script locally and the one where I execute it remotely, the TestExecutionSuccess.txt file is created.
However, in ONLY the local test run is the DBT.accdb file updated.
So lets talk about the problems
1 : You can run the code and open Excel when you run the code under your User account logged in.
2 : You can run the code and open Excel when you run the code under your the service account logged in.
3 : you can you the code But Excel will not load if you are not logged into the user.
Why?
This is about Interactive flag. When you are logged into a user then you have can load up GUI's using COM. If you are not logged into a user then you can not load a GUI.
Here is a more indeepth explanation from
Microsoft Interactive User
With ArcSet's guidance, I think I was able to figure out what the issue was. His answer led me down the path of investigating which version of powershell was running. Turned out the C# code was running Powershell x64 instead of x86 (32-bit) version. The office installation is 32-bit and hence why I couldn't run MSAccess.
I couldn't figure out how to run x86 version of Powershell from the C# code, but what I did was put the launch of MSAccess into a batch file and then executed the batch file from my powershell code. Not super clean, but it worked. Access is now running properly.
Here is the batch file code:
cd "C:\Program Files (x86)\Microsoft Office\Office14"
MSACCESS.EXE C:\test\DBT.accdb
and the new version of the PowerShell script:
try {
$msAccess = "C:\Program Files (x86)\Microsoft Office\Office14\msaccess.exe"
$fileLocation = "C:\test\executeTest.bat"
cmd.exe /c $fileLocation
$today = Get-Date
"SUCCESS: " + $today > "c:\test\TestExecutionSuccess.txt"
}
Catch
{
$_.Exception.Message > "c:\test\TestExecutionError.txt"
}
Related
So i made an application with multiple Powershell commands. They work perfectly when i run it through Visual Studio, but when i publish the application and run the .exe then for some reason the commands dont work, even on my pc and they give me errors i have tried changing the command itself but whatever command i type i keep getting the error from powershell.
// These are 2 of the commands i use
Get-LocalUser -Name Almar
Get-LocalUser -Name Almar.Description
// I run them using a Process function
Process cmd2 = new Process();
cmd2.StartInfo.FileName = $#"powershell ";
cmd2.StartInfo.Arguments = $#"Get-LocalUser -Name Almar.Description";
cmd2.StartInfo.RedirectStandardInput = true;
cmd2.StartInfo.RedirectStandardOutput = true;
cmd2.StartInfo.CreateNoWindow = true;
cmd2.StartInfo.UseShellExecute = false;
cmd2.Start();
cmd2.WaitForExit();
StreamReader reader = cmd2.StandardOutput;
string output = reader.ReadToEnd();
Even when i open a Command prompt or a powershell these commands work, only when i publish it and run it as an .exe it gives me errors.
Here's a screenshot of my publishing settings
Here's a screenshot of when i try to run the published .exe
As i said in the beginning, when i run the application in Visual Studio all the commands work but for some reason when the .exe is ran it just gives me errors.
If anyone know's why this is or did i mess something up while publishing please let me know.
I have an automation issue that I've tracked down to the following situation:
The PS script is being loaded via process.start in a C# program. If I run the script in the ISE, it runs fine. When running via process.start, it fails on the command:
Add-PSSnapin 'Microsoft.SharePoint.PowerShell'
With the error:
Add-PSSnapin : No snap-ins have been registered for Windows PowerShell version 4.
The command I'm using for process.start in .net is:
var Arguments #"-version 4.0 -ExecutionPolicy Bypass -noexit -file """ + filePath + #""" -XmlString """ + args + #""" -Verb RunAs"
var FileName = "powershell.exe"
var process = Process.Start(FileName, Arguments);
filePath is the path to the powershell script that is being executed.
This runs and attempts to run the script, but fails on the command shown above inside the script. The user account is the admin service account for the machine. The issue seems to be in how the .Net program is starting PowerShell, as I can run this script and these commands via the ISE and console if I do it manually (under the same service account). I just can't seem to find some combination of tricks to get the .Net program to be able to execute the PowerShell script under the correct profile, I guess.
Any thoughts?
PetSerAl's request was spot-on... when running the PowerShell script via the .Net program, it was running under x86, but when running it via ISE, it was running in x64. I re-compiled the .Net program against x64 and everything now works.
Thanks for the advice!
I'm doing a VSTO add in for Outlook in C# that calls PowerShell scripts to interact with the Exchange Online of Office 365.
It all works perfectly on my windows 10 machine with a machine level unrestricted PowerShell execution policy. However, I can't get this to run on the client's Windows 7 machine.
I think there are two issues. One that possibly his windows 7 PowerShell needs to be updated to work with my code, and second that I'm not properly setting the process execution policy. Here was my best effort to get the execution policy set to unrestricted (would bypass be better?).
using (PowerShell PowerShellInstance = PowerShell.Create())
{
StringBuilder OSScript = new StringBuilder("Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted;");
OSScript.Append(#"other really exciting stuff");
PowerShellInstance.AddScript(OSScript.ToString());
PowerShellInstance.Invoke();
}
Could someone point me the right direction? I know this doesn't work, as if I set the machine policy to restricted the other really exciting stuff doesn't happen, but if I set it to unrestricted then everything works.
I just created a new Console project and added this to Main:
using (PowerShell PowerShellInstance = PowerShell.Create())
{
string script = "Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted; Get-ExecutionPolicy"; // the second command to know the ExecutionPolicy level
PowerShellInstance.AddScript(script);
var someResult = PowerShellInstance.Invoke();
someResult.ToList().ForEach(c => Console.WriteLine(c.ToString()));
Console.ReadLine();
}
This works perfectly for me, even without running the code as administrator. I'm using Visual Studio 2015 in Windows 10 with Powershell 5.
Set-ExecutionPolicy works in the same way in Powershell 4 and 5, according to the Powershell 4.0 Set-ExecutionPolicy and the Powershell 5.0 Set-ExecutionPolicy.
Trying to do this using reflection.
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Reflection;
using Microsoft.PowerShell;
...
InitialSessionState iss = InitialSessionState.CreateDefault();
// Override ExecutionPolicy
PropertyInfo execPolProp = iss.GetType().GetProperty(#"ExecutionPolicy");
if (execPolProp != null && execPolProp.CanWrite)
{
execPolProp.SetValue(iss, ExecutionPolicy.Bypass, null);
}
Runspace rs = RunspaceFactory.CreateRunspace(iss);
rs.Open();
Please note: There are 5 levels (scope) of ExecutionPolicy in PowerShell (see about_execution_policies). This will set Process's ExecutionPolicy. This means if that ExecutionPolicy was defined with Group policy or Local policy ( UserPolicy or MachinePolicy ), this will not override ExecutionPolicy.
Check Get-ExecutionPolicy -List to see list of ExecutionPolicies defined in different scopes for your current process.
I am trying to use a custom snapin for powershell in my C# program. (The C# program is a modified version this)
I'm using the standard approach to setup the runspace:
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();
If I run this as is and scriptText contains the command "Get-PSSnapin" my snapin is missing. If I run "Get-PSSnapin -Registered" then I can see my snapin. If I use Add-PSSnapin, then it returns nothing and followup commands that I issue (which are implemented in the snapin will return):
...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
So, I amended my code to add the cmdlet to the runconfig:
RunspaceConfiguration runConfig = RunspaceConfiguration.Create();
PSSnapInException psEx = null;
runConfig.AddPSSnapIn("mySnapin", out psEx);
Runspace runspace = RunspaceFactory.CreateRunspace(runConfig);
Now, when I run it, I get:
error in script : Cannot invoke this function because the current host
does not implement it.
I tried both the x86 and 64 version. The snapin gets installed in the x86 programs so I did this by compiling for x86. If I do the 64 version, I get:
"Error in script : The Windows PowerShell snap-in 'mySnapin' is not
installed on this machine".
Confirming that this is specific to x86.
I also tried loading this as a module (desperation), but it doesn't work that way either. When I run:
get-command <command in mySnapin> | select Module, PsSnapin
The output doesn't have a module, just the snapin, hence it was silly to begin with.
I should note that this is installed by another program and I have no control over where it is install. I thought that might be a factor, but since it shows up with -Register I think it is finding without issue.
Edit:
I also tried import-module <path to dll>. This doesn't output anything and subsequent calls to functions in my snapin yield:
error in script : Cannot invoke this function because the current
host does not implement it.
Then again in C# since I wasn't clear on whether the import will be preserved across calls.
pipeline.Commands.Add("Import-Module");
var command = pipeline.Commands[0];
command.Parameters.Add("Name", #"<path to my snapin .dll>");
Any help getting this rolling would be greatly appreciated. Thank you!
I am trying to create a setup package that not only installs our app but also copies files to a remote app server and installs a service there. I thought that I would just override the install method in a custom action to have it kick off a powershell script to copy the files. Unfortunately when the code calls the powershell script I get this CmdletProviderInvocationException:
The system detected a possible attempt to compromise security. Please ensure that you can contact the server that authenticated you.
I was able to copy the code I am using to call the powershell script into a test project and it ran just fine, as I would expect since I have logged in to the server through windows explorer and so my user should be authenticated. I think the reason the script won't work when called by the installer must be that the installer switches users in order to get admin permissions to install the app, and the admin user is not authenticated (although I could be wrong).
Does anyone know how I could get this to work?
Here's the custom action code:
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
string scriptLoc = "c:\\sampleLocation";
pipeline.Commands.AddScript("&\"" + scriptLoc + "\\script.ps1\"");
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();
and here's the script:
$RemotePath = "\\SERVER\C$\Shared\Service"
$Source = "C:\sampleLocation\Service"
Get-ChildItem $Source -Recurse | Copy-Item -Destination $RemotePath
There are two major requirements for copying files to a network location:
your custom action should run without impersonation
the network location should have full permissions for Everyone
A MSI installation runs under the local system account. So it doesn't matter if you have permissions or not.
Since it's not easy to give permissions to SYSTEM account from a network machine, the easiest approach is to give full permissions to Everyone. This needs to be done on the machine which contains the shared folder.
According to #Cosmin Pirvu and Microsoft documentation :
The LocalSystem account is a predefined local account used by the service control manager. It has extensive privileges on the local computer, and acts as the computer on the network.
If your shared folder is on a computer that is on a domain, you can give full permissions to the client computer in spite giving it to Everyone.