Running PsExec From IIS: PsExecSVC hanging on remote host - c#

I am trying to run a .bat file on a remote host from a web page.
PSEXECSVC (on host) will hang and not close after the execution of the batch causing the server to wait indefinitely.
When running the exact same code (See at bottom) in a Console Application the service closes and everything is fine...
The weird part is when the batch file consists of a one liner echo:
#echo off
echo ------ Start -----
exit
PsExecSvc will close and "------ Start -----" is shown on the page. (This is what I want..)
On the other hand,
#echo off
echo ------ Start -----
echo echo2
exit
PSEXECSVC will hang at the end of execution...
When manually killing PSEXECSVC, only "------ Start -----" shows and StdErr
prints:
PsExec v1.98 - Execute processes
remotely
Copyright (C) 2001-2010 Mark
Russinovich
Sysinternals - www.sysinternals.com
The handle is invalid.
Connecting to novi2...
Starting PsExec service on novi2...
Connecting with PsExec service on
novi2...
Starting C:/dbInfo.bat on novi2...
Error communicating with PsExec
service on novi2:
No matter what is run in the batch file, only the first line of StdOut is redirected and psexecsvc hangs (but after the whole batch is executed :O ).
If running:
info.bat:
#echo off
cscript /nologo test.vbs
exit
test.vbs:
Set objOut = Wscript.StdOut
objOut.WriteLine "----------------------------------"
objOut.Writeline "Win32_OperatingSystem instance"
objOut.Writeline "----------------------------------"
objOut.close
Wscript.quit 666
A ConsoleApplication will print everything and return 666
IIS will only get "----------------------------------" in StdOut and psexecsvc will hangs...
Here is the code used to run psexec in C#...
Process proc = new Process();
ProcessStartInfo procInfo = new ProcessStartInfo(#"C:/PsExec.exe", #"\\novi2 -u Domain\usernameadmin -p Password C:/info.bat");
procInfo.UseShellExecute = false;
procInfo.RedirectStandardOutput = true;
procInfo.RedirectStandardError = true;
proc.StartInfo = procInfo;
proc.Start();
String output = proc.StandardOutput.ReadToEnd();
String err = proc.StandardError.ReadToEnd();
Trace.WriteLine("Out >> " + output);
Trace.WriteLine("Err >> " + err);
proc.Close();
I am using IIS 7, ASP MVC3 and .NET4.0 on the Server (Sample projects from VS2010) and WinXP SP3 for the host.
To avoid problems the ApplicationPool in IIS is using the same admin account as psexec.

The problem is likely the PSExecSvc on your remote host (novi2) did not clean up after itself and now needs to be deleted before it can run successfully. I now add the following at the end of each script that starts PSExec against a remote host:
sc \\novi2 delete PSExecSvc
Also, if you're instantiating PSExec on, and not against, a remote host, then you'll need to ensure you add the switch for accepting its EULA like so:
psexec \\HOST1 /accepteula -u userid -p password COMMAND
Hope that helps,
Lizz

Related

Can't start dotnet core process. Failed to add tools

I have a web application running in IIS that is starting a process with a .cmd file. The .bat file starts a dotnet core application.
This works fine on my local installation but when I deploy on a server I get the following error:
Failed to add 'C:\Users\Default.dotnet\tools' to the PATH environment
variable. Add this directory to your PATH to use tools installed with
'dotnet tool install'.
dotnet core and dotnet core sdk are installed. It works fine on the server if I run the .cmd file from a command prompt.
I have searched and can't find any hints on how to solve this.
private void RunMyCmd(string runMyCmdPath)
{
int exitCode;
ProcessStartInfo processInfo;
Process process;
processInfo = new ProcessStartInfo(runMyCmdPath);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
// *** Redirect the output ***
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardInput = true;
process = Process.Start(processInfo);
StreamWriter writer = process.StandardInput;
//string output = reader.ReadToEnd();
writer.WriteLine("a");
// Write the redirected output to this application's window.
// Console.WriteLine(output);
string output1 = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
process.WaitForExit();
// *** Read the streams ***
// Warning: This approach can lead to deadlocks, see Edit #2
exitCode = process.ExitCode;
if (exitCode != 0)
errorLogger.Error(string.Format("RunMyCmd: ExitCode({0}) - {1}", exitCode, error));
process.Close();
}
Edit: .cmd-file code:
#echo off
rem switch to on to test
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%"
set "datestamp=%YYYY%%MM%%DD%" & set "timestamp=%HH%%Min%%Sec%"
set "fullstamp=%YYYY%-%MM%-%DD%_%HH%-%Min%-%Sec%"
rem echo datestamp: "%datestamp%"
rem echo timestamp: "%timestamp%"
rem echo fullstamp: "%fullstamp%"
rem Go to script's directory
cd %~dp0
rem Read filenames if needed
set rules=%~dp0rules.json
set testcases=%~dp0testcases.csv
if not exist %rules% (
echo file not found. Type in full file name and Enter
set /p rules="Rules file: "
)
if not exist %rules% (
echo We did not find rules file: %rules%
exit /B 1
)
if not exist %testcases% (
echo testcases not found. Type in full file name and Enter
set /p testcases="Testcases file: "
)
if not exist %testcases% (
echo We did not find testcase file: %testcases%
exit /B 1
)
rem Create filename for results csv
set filename="results_%fullstamp%.csv"
rem Run
cd AppFolder
dotnet run --no-build %rules% %testcases% %filename%
move %filename% ../results/
PAUSE
Problem solved.
I installed the Web application on another server and got the following exception:
Failed to add 'C:\Windows\system32\config\systemprofile\.dotnet\tools' to the PATH environment variable. Add this directory to your PATH to use tools installed with 'dotnet tool install'.
Because I got 2 similar exceptions I figured the problem might be with permissions on the folder.
So I added modify permissions for the service account to the folder
C:\Windows\system32\config\systemprofile
Which solved the problem. After running the app these new folders was created:
C:\Windows\System32\config\systemprofile\.dotnet
C:\Windows\System32\config\systemprofile\.nuget
I then added the same permissions on my prod server but for the folder
C:\Users\Default
The question that remains is why two servers are locating .dotnet folders in different paths?
Got similar issue after I renamed my core application dll. Figured my application DLL isn't being found for activation anymore. So i checked inside web.config turns out forgot to rename dll.
dotnet itself should not be writing any files to C:\Users\Default.dotnet\tools, so the permissions should not be necessary provided the application can be found.

Shellscript is not executing on production server when invoked with c# code on cygwin terminal

I have a shell script that I have to run on windows server which is the staging server
The name of the shell script is 'texteffect'
I have created a batch file named CurveTextEffect.bat that is containing this command
#echo on
SET allParameters=%*
C:\cygwin64\bin\bash --login -c "%allParameters%"
and I am invoking this bat file with this code in c#
Note the whole string is prepared dynamically but final string looks like this
string cmd = "CurveTextEffect.bat texteffect -t 'USA BALL' -S 700x -s outline -e concave -d 0.5 -f Impact -p 29.7286291125 -c '#FFFFFF' -l 0.41289762 -b none 'D:/1.0.0/CurvedImage.png'"
here "CurveTextEffect.bat" is batch file name and "texteffect" is the shellscript name
ProcessStartInfo startInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Normal,
UseShellExecute = true,
FileName = "cmd.exe",
WorkingDirectory = Environment.CurrentDirectory,
Arguments = string.Format(#"/C " + cmd),
CreateNoWindow = false
};
try
{
using (Process process = new Process())
{
process.StartInfo = startInfo;
process.EnableRaisingEvents = true;
process.Start();
process.WaitForExit();
}
}
catch (Exception ex)
{
// Log message in logger
// Log the parameters and the enviournment path in the logger
_context.Logs.Add(new Logs()
{
LogMessage = ex.Message,
CreatedOn = DateTime.UtcNow,
LogLevel = Enum.GetName(typeof(LogLevel), LogLevel.Error)
});
}
When I invoke this shell script on the server manually in the cygwin terminal then it's works fine
Even when I invoke this bat file with arguments it works fine
When I am invoking cygwin terminal into IIS site, which is installed on windows server through the above c# code the it wont work
I have also checked the logs of the IIS where It says texteffect no such command
I have also configured the path of the cygwin and the shellscript in the environment variables as instructed here but then also it says command not found : as done here
Can some one please help me on that?
I have followed the steps instructed here for installing the Cygwin with ImageMagick
Reference URL:- http://im.snibgo.com/cygwin.htm
When I run this on local IIS it works fine but when it's deployed on staging the shell script does not run
Is any way to identify that shell script is executing on the Staging windows server or not ?
Windows version on the staging site is : Windows Server 2016 Datacenter
I am using this version of ImageMagick-6.9.8-4-Q16-x86-dll.exe ImageMagick
These are my configured paths in environment variables
C:\cygwin64\bin
C:\cygwin64\usr\local\bin
D:\MyScripts

How can I know whether RabbitMQ application has started

I have a c# code that installs rabbitmq 3.7.4, erlang 20.2 on windows server 2012 R2 and I need to know when the application (not the service) has started. After running rabbitmq-service install and rabbitmq-service start I'm looking for a command line that will indicate that the application is running. I'm aware of the wait pid_file, wait --pid pid command but can't locate the pid file on my machine. The documantaion says:
This command will wait for the RabbitMQ application to start at the node. It will wait for the pid file to be created if pidfile is specified
specified where?
rabbitmq-echopid.bat returns:
The system cannot find the path specified.
On Windows, RabbitMQ does not create a PID file by default, so you have to discover the PID and then pass it as an argument: rabbitmqctl.bat wait -P PID
To discover the PID, you can run the following using the name of your RabbitMQ node:
.\rabbitmq-echopid.bat rabbit#my-hostname
At this time, there is a bug where The system cannot find... will be echoed before the PID is echoed. I filed this bug and will have a fix in soon, but in the meantime you can edit the rabbitmq-echopid.bat script to change !TDP0! to %TDP0%.
You can also use any other Windows tool to find the PID of the erl.exe process running RabbitMQ - see the script for an example of wmic.exe, or you could use tasklist, or Powershell, etc.
On windows, you can run the following batch script:
START /B rabbitmq-server
START /wait cmd /c "rabbitmq-echopid.bat -n rabbit#`hostname` > rabbitmq_pid.txt"
set /p PID=<rabbitmq_pid.txt
echo %PID%
del rabbitmq_pid.txt
cmd /c "rabbitmqctl wait -P %PID%"
Note that for the rabbitmq-echopid command to work, you have to add an -n before the nodename.
Moreover, in the above batch script, the nodename is dynamically generated by combining "rabbit#" withe the hostname windows command (inside backticks).

psexec command invoking from Windows Service

I created Windows Service problem which invokes psexec and run .exe in the remote Server. Every thing work fine, when i try to do run in debug mode of invoking pscommand code # console application, when i try to run pscommand from Windows service, It hangs out without any reason. Is there any reason or alternative.. psexesvc doesnot start on remote server
Here is the pscommand i used
psexec -accepteula \\XYZServer -u -p -h \ShareCompName\Component.exe.
There is no error message.
I found reason for hang state, basically psexec command is calling .exe application, where that exe aplication is performing Admin activity. When PSEXEC command is having -h parameter , then it asking psexec command to execute run as administrator. Since target server where psexec gets executed is having UAC enabling, It is waiting for user input , until user click Yes or NO. application remain in hang state. SO i added extra parameter -i along with -h which automatically takes care of above explained situation.
psexec -accepteula \XYZServer -u -p -h -i \ShareCompName\Component.exe.

running a batch file through c# console app. Commands get ignored

i'm trying to execute a .bat file through a c# console application using code from here:
Service hangs up at WaitForExit after calling batch file
Kevin's solution kinda works, but some commands in my .bat file get ignored for some reason, but when i manually execute the .bat file all commands work just fine.
e.g. xcopy command doesn't work while executing .bat from console app, but start command works fine.
Any idea why this happens?
p.s. recently i found that if the program is being launched from command prompt, it works well. How come? Still i need to put it on autorun, so this doesn't solve the problem.
Also, if launched by clicking on exe file, output shows
xcopy folder1 folder2
but if launched from command prompt, output shows
xcopy folder1 folder2
smth/smth.smth copied
....
5 files copied.
And it actually is being copied.
proc.StartInfo.FileName = target;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
proc.WaitForExit
(
(timeout <= 0)
? int.MaxValue : timeout * NO_MILLISECONDS_IN_A_SECOND *
NO_SECONDS_IN_A_MINUTE
);
errorMessage = proc.StandardError.ReadToEnd();
proc.WaitForExit();
outputMessage = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
Batch file commands do not get ignored when you execute the command processor from a service. They however easily fail and can do so unobserved since you cannot see their output. Typical reasons for failure are having the ProcessStartInfo.WorkingDirectory not set correctly so that relative paths no longer work or trouble caused by the service running with a different user account that doesn't have the same rights as the one you use from the desktop.
Diagnose problems by redirecting output to a file, run cmd.exe /c and use the > operator. Append 2>&1 so that the file contains both regular and error output. And by using the %errorlevel% variable and EXIT command judiciously so you can discover that execution failed by using the Process.ExitCode property.

Categories

Resources