Console application starting another process environment variables not accessible - c#

I have a VB6 executable which is accessing some system environment variables. I have implemented a .NET console application which checks if those environment variables exist, creates them if needed, and then runs the VB6 application by calling Process.Start.
Doing this, the VB6 application cannot find the environment variables and it says they don't exist.
If I run the VB6 application from Windows Explorer it works fine and can find the variables.
So it seems the VB6 app is running under the context of .NET console app and cannot access the system environment variables!
Code to set the environment vars .NET Cosnole app:
foreach(var varObject in Variables)
{
var envVar = Envrionment.GetEnvironmentVariable(varObject.Name ,
EnvironmentVariableTarget.Machine);
if(string.IsNullOrEmpty(envVar)
{
Environment.SetEnvironmentVariable(varObject.Name,varObject.Value,
EnvironmentVariableTarget.Machine);
}
}
Code to run the VB6 app from .NET Cosnole app:
var processInfo = new ProcessStartInfo(VB6ApplicationFilePath);
processInfo.UseShellExecute = true
processInfo.WindwoStyle= ProcessWindowStyle.Hidden;
Process.Start(processInfo);

A copy of a program's environment is passed to a program that it starts. As it is a copy the second program only sees the state it was in when given it (and changes it made). No other program can change another program's environment.
When using ShellExecute (which you tell ProcessStart to) you are asking Explorer to start the program for you. The program will get a copy of Explorer's environment.
When changing the system environment, programs can send a message to all windows open saying environment has changed (as setx does - see setx /?). But ONLY Explorer.exe pays attention to this message. So only programs started by explorer after explorer receives this message will see the changes.
These are the API calls that .NET calls. In Windows all programs are started by CreateProcessEx (or older programs CreateProcess). Shellexecute and ShellexecuteEx process the command like you typed it in Explorer's Start - Run dialog (Winkey + R) then changes it and calls CreateProcessEx.
At the command prompt. Type
set MyCat=PewResearch
cmd /k echo %MyCat%
We set an environment variable, start a new command prompt that prints that variable.
This is the message that notifies
WM_SETTINGCHANGE
The system sends the WM_SETTINGCHANGE message to all
top-level windows when the SystemParametersInfo function changes a
system-wide setting or when policy settings have changed.
Applications should send WM_SETTINGCHANGE to all top-level windows
when they make changes to system parameters. (This message cannot be
sent directly to a window.) To send the WM_SETTINGCHANGE message to
all top-level windows, use the SendMessageTimeout function with the
hwnd parameter set to HWND_BROADCAST.

Related

Open Network And Sharing Center programatically without explorer.exe

Is there a way of opening this from a C# application without needing explorer.exe to be running? I have a Windows 10 IoT device running with a custom shell, but needs to be able allow the user to set up WiFi connections.
I have tried this:
ProcessStartInfo psInfo = new ProcessStartInfo("control.exe", "/name Microsoft.NetworkAndSharingCenter");
However while this works fine when running normally in Windows, when I run it in the custom shell (explorer.exe is not running), nothing happens.
This differs from the Network Connections applet which runs fine even within the custom shell...
ProcessStartInfo psInfo = new ProcessStartInfo("rundll32.exe", "shell32.dll,Control_RunDLL ncpa.cpl");
Is there a way to get rundll32 to run the "Network and Sharing center"? I can't find another .cpl that does it and any research on the 'net just points me back to the original command I tried above.

Launch a command shell from a console application run via Windows Task Scheduler

I have a Windows console application that is launched via a schedule setup in Task Scheduler. This console application, as part of its normal runtime, will launch a command prompt in order to run a java program. No, I have no control over the design of the Java program. It was supplied to me as is and I have no rights or access to make changes to it. I also cannot implement it in another language. I must use what was given to me.
At any rate, when my console application tries to run the command prompt it will work just fine if I'm launching the application manually. However, when I try it as an action within Task Scheduler, my console application will start and run as expected until it needs to launch the command prompt. At this point, the console application exits. No error message or code is provided.
How do I get the command prompt window to start as a new window from within my console application when no one is logged into the server?
Thanks for any hints or suggestions you can provide.
* UPDATE *
Here is the code snippet that launches the program from within my console application:
string parameter_save_path = #"C:\output\folder"
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo start_info = new System.Diagnostics.ProcessStartInfo();
start_info.WorkingDirectory = #"C:\mtselect-client";
start_info.FileName = "cmd.exe";
start_info.Arguments = "/C run.bat \"" + parameter_save_path + "\"";
process.StartInfo = start_info;
process.Start();
process.WaitForExit();
The run.bat is what launches the java program.
I think it's too late for this message, but...
Maybe in your batch file you are running your java application with something like: java -jar ApplicationName
First I would do should be comment out the "#echo off" from the batch file, next trace out the batch lines with one echo "x" (being x a natural number starting from 1 and increasing by 1 in each ocurrence). Next I will add a line with java -version, and so I will be sure java app is installed and accesible.
Maybe java needs be ran by an authenticated user and so have java_home defined. Maybe the application needs some JVM parameters like memory size, etc.
Have good luck, tell me and I will try to help

Batch process to pass information back to console application window

I have a console application that runs .bat and .vbs files.
The method which starts these processes is as follows:
public void runProcess(string aPath,string aName,string aFiletype)
{
string stInfoFileName;
string stInfoArgs;
if(aFiletype == "bat")
{
stInfoFileName = (#aPath + #aName);
stInfoArgs = string.Empty;
}
else
{ //vbs
stInfoFileName = #"cscript";
stInfoArgs = "//B //Nologo " + aName;
}
this.aProcess.StartInfo.FileName = stInfoFileName;
this.aProcess.StartInfo.Arguments = stInfoArgs;
this.aProcess.StartInfo.WorkingDirectory = #aPath;
this.aProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
this.aProcess.Start();
Console.WriteLine("information passed from batch: ???");
this.aProcess.WaitForExit(); //<-- Optional if you want program running until your script exit
this.aProcess.Close();
}
The current .bat files which it is starting are used to send data over ftp (ftp, ftps, or sftp).
When the process is running all information is shown in the process windows e.g. an error might occur, the file is not transferred and a message detailing this is displayed in this "child" process window. Once the process has finished the "child" window disappears along with the messages.
Can I somehow return this useful information to my main console application window?
Check process exit code (Process.ExitCode) and/or capture console output.
See Capturing console output from a .NET application (C#)
Though you should better use some native .NET SFTP/FTP library.
For SFTP, see SFTP Libraries for .NET
For FTP and FTPS, use can use the FtpWebRequest from .NET framework.
If you want all-in-one solution, I can humbly suggest you my WinSCP .NET assembly. With the assembly, you can have the same code for SFTP, FTP and FTPS. Internally, the assembly actually runs WinSCP console application. So it is doing the same thing you are trying to code yourself.
If you set this.aProcess.StartInfo.UseShellExecute to false then the child process should use the existing console window.
For batch files, this change also means you'll need to explicitly invoke cmd /c to run them, in exactly the same way you're currently invoking cscript /B to run .vbs scripts.

Process.Start won't work

I am trying to launch a process from a web page's back-end code/app pool. This process will launch an App that i built myself.
For some reason, the process only works / runs when i start it from VS2013... it never works when i launch it from IIS(7.5) itself.
I am on a Windows 7 machine (both IIS host, and App location), and I've setup my web site to only be accessible via internal network.
Here's the code, followed by the config / attempts to fix the issue:
protected void btn_DoIt_Click(object sender, EventArgs e)
{
string file_text = this.txt_Urls.Text;
if (!String.IsNullOrWhiteSpace(file_text))
File.WriteAllText(ConfigurationManager.AppSettings["filePath"], file_text);
ProcessStartInfo inf = new ProcessStartInfo();
SecureString ss = GetSecureString("SomePassword");
inf.FileName = #"........\bin\Release\SomeExecutable.exe";
inf.Arguments = ConfigurationManager.AppSettings["filePath"];
inf.UserName = "SomeUserName";
inf.Password = ss;
inf.UseShellExecute = false;
//launch desktop app, but don't close it in case we want to see the results!
try
{
Process.Start(inf);
}
catch(Exception ex)
{
this.txt_Urls.Text = ex.Message;
}
this.txt_Urls.Enabled = false;
this.btn_DoIt.Enabled = false;
this.txt_Urls.Text = "Entries received and process started. Check local machine for status update, or use refresh below.";
}
Here are the things I've tried to resolve the issue:
Made sure the executing assembly was built with AnyCPU instead of
x86
Ensured that the AppPool that runs the app, also runs under the same account (SomeUsername) as the ProcessStartInfo specified.
Ensured that the specific user account has full access to the executable's folder.
Ensured that IIS_USR has full access to the executable's folder.
Restarted both the app pool and IIS itself many times over implementing these fixes
I am now at a loss as to why this simply will not launch the app... when i first looked into the event log, i saw that the app would die immediately with code 1000:KERNELBASE.dll, which got me on the AnyCPU config instead of X86 fix... that fixed the event log entries but the app still doesn't start (nothing comes up in task manager), and i get no errors in the event log...
if someone could help me fix this problem i would really appreciate it. This would allow me to perform specific tasks on my main computer from any device on my network (phone, tablet, laptop, etc etc) without having to be in front of my main PC...
UPDATE
The comment to my OP, and ultimate answer from #Bradley Uffner actually nailed the problem on the head: My "app" is actually a desktop application with a UI, and in order to run that application, IIS would need to be able to get access to the desktop and the UI, just like if it were a person sitting down in front of the PC. This of course is not the case since IIS is running only as a service account and it makes sense that it shouldn't be launching UI programs in the background. Also see his answer for one way of getting around this.
Your best bet might be to try writing this as 2 parts. A web site that posts commands to a text file (or database, or some other persistent storage), and a desktop application that periodically polls that file (database, etc) for changes and executes those commands. You could write out the entire command line, including exe path command arguments, and switches.
This is the only way I can really think of to allow a service application like IIS to execute applications that require a desktop context with a logged in user.
You should assign a technical user with enough high priviliges to the running application pool. By default the application pool is running with ApplicationPoolIdentity identy which has a very low priviliges.

Disable "The publisher could not be verified" while tarting .NET console app from share folder

I am trying to run a .NET console app from a shared network folder using method Process.Start.
Everytime the console app starts I get the message "The publisher could not be verified" and Windows asks for user confirmation. How can I disable this dialog? I do not want to buy a digital certificate.
within your .net application when you use "Process.Start"
use the feature Process.StartInfo.UseShellExecute = false.
so ...
Process proc = new Process();
proc.StartInfo.UseShellExecute = false;
what this does is it allows you to launch EXES (and only exes) directly without using the Explorer(shell).
This will bypass any IE Security Zone checks. The Explorer by default includes the IEZone check and thus will
give you a security warning if the application you are running is not 'trusted' (specifically in a trusted zone).
Now you cannot use 'false' if you want to launch a 'PDF' for example. This only works for Exes.
Last bit of information:
http://technet.microsoft.com/en-us/library/bb457006.aspx
http://technet.microsoft.com/en-us/library/dd349795(WS.10).aspx
these bits of info, which a MS rep just provided me, may provide a way to trust the publisher of a signed application by using Software Restriction Policies. I haven't looked into this yet, but for those that need to continue with this further... this looks like another way to address part (1) .

Categories