Process doesn't start with a correct user name - c#

I am working on renewing an application. The old code had a main method which went through the running processes on windows and checked to see if a certain required process which is a part of the application is running, and if not it starts it. This is how it looks:
Process[] localProcesses = Process.GetProcesses(Environment.MachineName);
bool isHostAlive = false;
foreach (Process localProc in localProcesses)
{
if (localProc.ProcessName == "processIneed")
{
isHostAlive = true;
}
}
if (!isHostAlive)
{
try
{
Process.Start(Application.StartupPath + #"\bin\processIneed.exe");
}
....
Now what I did was adding an installer class in which I override the Commit method and there I'm activating the process so it will automatically run after installing the application. It looks like this:
string path = Context.Parameters["targetdir"].Replace(#"\\", #"\");
path += #"bin\processIneed.exe";
Process.Start(path);
The problem is that in the old way without activating the process during installation everything worked fine. When I'm starting the process in the new way I've implemented, I see that the path is being built correctly and the process do run in the backgroung but the application just doesn't work as it should.. It kinda "half" works.. I'm not getting any errors or exceptions but it just doesn't work.
The only difference I did notice is that with the old code the process was started under the user name which logged in to windows (user name and password entered in the login screen), while in the new code, the process starts under the user SYSTEM.
Is there a way to start the process from the installer class with the correct credentials? I want to clarify that I don't want to somehow request the password from the user and I don't want to save it or something.. just start with the currently logged on credentials and not with the SYSTEM user.

Related

Error while starting a WPF-Application on System-Startup

I have a WPF-Application that I would like to start automatically if I start my Computer.
I have a window where a user can configure some settings for the application, one of the possible configuration options is a checkbox, that allows the user to dis- or enable the application to automatically start on the System-Startup.
This is how I set or delete the value in the Registry, depending on the users choice in the Checkbox:
try
{
var currentAssembly = Assembly.GetExecutingAssembly();
var rkApp = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
if (settingsViewModel.AutostartEnabled)
{
rkApp.SetValue(currentAssembly.GetName().Name, currentAssembly.Location);
}
else
{
rkApp.DeleteValue(currentAssembly.GetName().Name, false);
}
}
catch (Exception exception)
{
}
My Problem is, that even though the Application gets registered and can also be seen in the Autostart-Section within the Task-Manager, that I get the following error every time I restart my computer to check if the Appliction is started:
"You are attempting to open a file of type Application extension (.dll)"
So what am I doing wrong? Is there any way to avoid this error or to fix it? I already tried adding an application manifest file to my project to always start my Application as an Administrator. But that didn't seem to work either.
I'd appreciate any help.
Try to use System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName instead of currentAssembly.Location.
This should give you the path of the running executable. Assembly.GetEntryAssembly does not.

ASP.NET Process.Start work background in task Manger but not come on front on IIS8.5 (Windows 8.1)

i want to execute a .EXE file in mvc 3 application when we run this project locally on browser it work perfectly . Problem is that when we publish this project and host it on the IIS(8.5) server on window 8.1 when we click the button code executed and process start in Task Manger but app not shown on front .
For examples in this case we execute notepad.exe file .
Following is our code in html we make a one button when user click on that button controller method is called that run code .
when user click on button this is cod that is executed.
$("#Button11").click(function (event) {
$.post("/Account/Start_Appl", {}, function (data) {
});
event.preventDefault();
});
and start Start_Appl Method inside Account controller have following line of code .
public string Start_Appl()
{ string path="C:\\Windows\\System32\\notepad.exe";
ProcessStartInfo psi = new ProcessStartInfo();
psi.UseShellExecute = true;
psi.LoadUserProfile = true;
psi.WorkingDirectory = path;
psi.FileName = path;
Process.Start(psi);
return "ok";
}
i want to execute .EXE file with iis(8.5) any solution to this problem .
i check on the internet but can not find any proper solution for this problem.
i also check this link but not give any help .
ASP.NET Process.Start not working on IIS8 (Windows 8.1)
OK, first off, this is a very odd thing to do - there is going to be a better approach for whatever your problem is. That said, what I would do in this situation is:
create a database with a JOB_QUEUE table. exactly what is in this table is up to you, but I'd suggest an ID, a date_added, something to indicate what the job should consist of (e.g. the name of the exe to run?) and a flag to indicate the status of the job (pending/in progress/failed/completed)
modify controller to insert a record into this table with a 'pending' status (this is ALL it does)
write a separate application that runs in a user process (windows forms or console application). this application could run on the server which hosts IIS or a separate one - all it needs it access to the same database
Make this separate application periodically check the job queue table for jobs with a pending status.
When a new job is detected, the application updates the database so the job is 'in progress' and runs the job. if successful it updates the job to be 'completed' and if it fails it updates it to be 'failed'.
It then goes back to simply monitoring the table.
There are lots of other things you could use in place of the database for a queue, but this would be quick to write and easy to debug/test as well as making it easy to add multiple clients and persist historical info, and add controller methods to report on jobs requested/completed and progress.
For execution external .exe file in iis(8.5) and window 8.1 . we used
Custom URL Protocol for Invoking Application Techniques check this link
Custom URL Protocol
i have change my Start_Appl function is as .
public string Start_Appl()
{
try
{
string myAppPath = "C:\\Windows\\System32\\notepad.exe";
RegistryKey key = Registry.ClassesRoot.OpenSubKey("myAppa"); //open myApp protocol's subkey
if (key == null) //if the protocol is not registered yet...we register it
{
key = Registry.ClassesRoot.CreateSubKey("myAppa");
key.SetValue(string.Empty, "URL: myApp Protocol");
key.SetValue("URL Protocol", string.Empty);
key = key.CreateSubKey(#"shell\open\command");
key.SetValue(string.Empty, myAppPath + " " + "%1");
}
key.Close();
}
catch (Exception e) {
return e.Message.ToString();
}
return "ok";
}
we first register a key if it is not already create and set value and after that we make a button on my aspx page is as
<input type="submit" name="Launch" id="Launch" value="Launch Custom URL" onclick="LaunchURLScript()">
When user click on button the function LaunchURLScript is call and inside this function we write following code in it
function LaunchURLScript() {
$.post("/Account/Start_Appl", {}, function (data) {
if (data = "ok") {
alert("ok");
var url = "myAppa:"; window.open(url); self.focus();
}
});
}
for inside we first call controller method to make URl protocol if not already exist and finally we open new window that lunch my note pad exe file .
in this way we solve our problem.

How to give IIS AppPool Desktop Rights

The action I need help about, is to execute a EXE file on own servers disk from a intranet-webpage, which IIS are on same server-installation. The webpage use a business layer to execute a ProcessStart together with given parameters.
When I perform the execution from web, the taskmanager show me that the application are starting up with the IIS AppPool of webpage as user. Few seconds later it's killed. In my database logs, I can see;
The Microsoft Jet database engine cannot open the file '\\computer\pathfile.ext'. It is already opened exclusively by another user, or you need permission to view its data.
That's correct. The EXE tool are, in turn, loading files from other computers. This is a special behavior which are well studied and well working while using the tool from desktop.
My goal/question,
I want this web-function-call behave with desktop rights. Is it possible at all?
The IIS AppPool have a regular setup with account ApplicationPoolIdentity. I appeared to be "lucky unwise", without knowledge about how much IIS 7.5 and Windows Server 2008 R2 raised the security model since <=IIS6.
I tried to change the app-pool user to NetworkService, Administrator.
I tried to set the application with app-pool as exec/read right
I even tried to let webapp to run a batch-file with a call to application inside..
Then I was begin to change the ProcessStart-behavior. And here, I
don't know much of what to do. I tried to add VERB runas. Force a
password prompt is not a solution here. I tried to simulate a
username/password. No luck there. I also tried to add runas /user:
blabla as parameters with ProcessStart, after used /savecred in a
desktop command window once. No luck there.
Maybe this should work but I just don't understand the correct setup of properties. I add the ProcessStart code snippet below, also added some commented code to let you see what I tried.
public string RunProcess(ApplicationType type, int param)
{
currentSelection = GetApplicationType(type);
ProcessStartInfo info = new ProcessStartInfo(currentSelection.Path);
info.CreateNoWindow = false;
info.UseShellExecute = true;
//info.UseShellExecute = false;
//info.ErrorDialog = false;
//info.UserName = "dummyUsEr";
//info.Password = this.SecurePwd("DummyPWd");
info.WindowStyle = ProcessWindowStyle.Normal;
info.Arguments = string.Format(" {0}", param.ToString());
using (Process exec = Process.Start(info))
{
try
{
exec.WaitForExit();
}
catch
{
}
}
return output;
}
EDIT
Just to be clear, and perhaps help some another guy/girl browsing to this question, I attach the snippet of Password-generation,
protected System.Security.SecureString SecurePwd(string pwd)
{
SecureString securePwd = new SecureString();
foreach (char ch in pwd.ToCharArray())
securePwd.AppendChar(ch);
return securePwd;
}
I see that you've tried putting in a specific username and password for the process start impersonation, but you say that the process accesses files on another computer and I don't see any mention of specifying a domain name which presumably you would need to access remote files?
So like this:
info.Domain = "domainname";
info.UserName = "dummyUsEr";
info.Password = "DummyPWd";
Also, what does this.SecurePwd() do and have you tried it with just the straight password string that you're passing into it?

How to set "interact with desktop" in windows service installer

I have a windows service which runs under system account and executes some programs from time to time (yeah,yeah, I know that's a bad practice, but that's not my decision). I need to set the "interact with desktop" check, to see the gui of that executed programs, after the service is installed. I've tried several ways, putting the code below in AfterInstall or OnCommited event handlers of my service installer:
ConnectionOptions coOptions = new ConnectionOptions();
coOptions.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope mgmtScope = new System.Management.ManagementScope(#"root\CIMV2", coOptions);
mgmtScope.Connect();
ManagementObject wmiService = new ManagementObject("Win32_Service.Name='" + ServiceMonitorInstaller.ServiceName + "'");
ManagementBaseObject InParam = wmiService.GetMethodParameters("Change");
InParam["DesktopInteract"] = true;
ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", InParam, null);
or
RegistryKey ckey = Registry.LocalMachine.OpenSubKey(
#"SYSTEM\CurrentControlSet\Services\WindowsService1", true);
if(ckey != null)
{
if(ckey.GetValue("Type") != null)
{
ckey.SetValue("Type", ((int)ckey.GetValue("Type") | 256));
}
}
both of these methods "work". They set the check, but after I start the service it launches the exe - and gui isn't shown! So, if I stop the service, recheck and start it again - bingo! everything starts and is shown. The second way to achieve the result is to reboot - after it the gui is also shown.
So the question is: Is there a correct way to set "interact with desktop" check, so it'll start working without rechecks and reboots?
OS: Windows XP (haven't tried Vista and 7 yet...)
private static void SetInterActWithDeskTop()
{
var service = new System.Management.ManagementObject(
String.Format("WIN32_Service.Name='{0}'", "YourServiceName"));
try
{
var paramList = new object[11];
paramList[5] = true;
service.InvokeMethod("Change", paramList);
}
finally
{
service.Dispose();
}
}
And finally after searching the internet for a week - I've found a great working solution:
http://asprosys.blogspot.com/2009/03/allow-service-to-interact-with-desktop.html
Find the desktop to launch into. This
may seem facetious but it isn't as
simple as it seems. With Terminal
Services and Fast User Switching there
can be multiple interactive users
logged on to the computer at the same
time. If you want the user that is
currently sitting at the physical
console then you're in luck, the
Terminal Services API call
WTSGetActiveConsoleSessionId will get
you the session ID you need. If your
needs are more complex (i.e. you need
to interact with a specific user on a
TS server or you need the name of the
window station in a non-interactive
session) you'll need to enumerate the
Terminal Server sessions with
WTSEnumerateSessions and check the
session for the information you need
with WTSGetSessionInformation.
Now you know what session you need to
interact with and you have its ID.
This is the key to the whole process,
using WTSQueryUserToken and the
session ID you can now retrieve the
token of the user logged on to the
target session. This completely
mitigates the security problem of the
'interact with the desktop' setting,
the launched process will not be
running with the LOCAL SYSTEM
credentials but with the same
credentials as the user that is
already logged on to that session! No
privilege elevation.
Using CreateProcessAsUser and the
token we have retrieved we can launch
the process in the normal way and it
will run in the target session with
the target user's credentials. There
are a couple of caveats, both
lpCurrentDirectory and lpEnvironment
must point to valid values - the
normal default resolution methods for
these parameters don't work for
cross-session launching. You can use
CreateEnvironmentBlock to create a
default environment block for the
target user.
There is source code of the working project attached.
Same as Heisa but with WMI. (code is Powershell, but can be easily ported to C#)
if ($svc = gwmi win32_service|?{$_.name -eq $svcname})
{
try {
$null = $svc.change($svc.displayname,$svc.pathname,16,1,`
"Manual",$false,$svc.startname,$null,$null,$null,$null)
write-host "Change made"
catch { throw "Error: $_" }
} else
{ throw "Service $svcname not installed" }
See MSDN: Service Change() method for param description.

Starting time of a process

How do I retrieve the starting time of a process using c# code? I'd also like to know how to do it with the functionality built into Widows, if possible.
public DateTime GetProcessStartTime(string processName)
{
Process[] p = Process.GetProcessesByName(processName);
if (p.Length <= 0) throw new Exception("Process not found!");
return p[0].StartTime;
}
If you know the ID of the process, you can use Process.GetProcessById(int processId). Additionaly if the process is on a different machine on the network, for both GetProcessesByName() and GetProcessById() you can specify the machine name as the second paramter.
To get the process name, make sure the app is running. Then go to task manager on the Applications tab, right click on your app and select Go to process. In the processes tab you'll see your process name highlighted. Use the name before .exe in the c# code. For e.g. a windows forms app will be listed as "myform.vshost.exe". In the code you should say
Process.GetProcessesByName("myform.vshost");
Process has a property "StartTime":
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.starttime.aspx
Do you want the start time of the "current" process? Process.GetCurrentProcess will give you that:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.getcurrentprocess.aspx
In Code
Suppose you want to find the start time of Notepad, currently running with PID 4548. You can find it, using the PID or the process name, and print it to the debug window like this:
//pick one of the following two declarations
var procStartTime = System.Diagnostics.Process.GetProcessById(4548).StartTime;
var procStartTime = System.Diagnostics.Process.GetProcessesByName("notepad").FirstOrDefault().StartTime;
System.Diagnostics.Debug.WriteLine(procStartTime.ToLongTimeString());
In Windows
You can use Process Explorer, which has an option to display the process start time, or you can list all the currently running processes, and their start times, from the command line with the following:
wmic process get caption,creationdate
You can get process metadata by inspecting the Process object returned by Process.GetProcessesByName().
System.Diagnostics.Process.GetProcessById(xxx).StartTime;//fails for certain processes with access denied

Categories