|
Don't build the command line argument string inside the Start method. Build it into a variable so you can see EXACTLY what is being sent to the Start method.
|
|
|
|
|
Yeah, I've done that and its EXACTLY what I ran under the runas command. I've tried both the code I posted (while impersonating the domain account that has admin rights) as well as the version of Start where you pass in the username, password & domain. In addition, as proof that my impersonation code is working, I'm able to start & stop the service remotely with the service control manager class. I'm also able to execute pskill remotely (to kill a process).
|
|
|
|
|
SledgeHammer01 wrote: I've done that and its EXACTLY what I ran under the runas command
Seriously?? "<the service name>" ?? That's not exactly what you're running at the command line...
If you're getting the black CMD window to show up and then disappear, it means that you're:
1) Launching the command as a user that doesn't have permissions to execute the SC command on the target machine.
2) The service name isn't correct.
3) Something else in the command line isn't correct.
To check to see who the command line is running as, change the Start call to launch .Start("CMD", "/K WHOAMI")
After you've verified who the command is running as, you can alter your command line to launch the SC command and have to command prompt stick around: .Start("CMD", "/K <your entire SC command line here>")
Oh, remember what I said about building the command line in a seperate variable?? This is where is comes in handy...
|
|
|
|
|
Dave Kreskowiak wrote: Seriously?? "<the service name>" ?? That's not exactly what
you're running at the command line...
You know that I "censored" that for the forum, right?
Dave Kreskowiak wrote: 1) Launching the command as a user that doesn't have permissions to execute the
SC command on the target machine.
As I stated, I can start and stop the service with the Service Control Manager class, so the user is correct.
Dave Kreskowiak wrote: 2) The service name isn't correct.
As I stated, I can start and stop the service with the Service Control Manager class, so the service name is correct.
Dave Kreskowiak wrote: Oh, remember what I said about building the command line in a seperate
variable?? This is where is comes in handy...
As I stated, I did that.
Dave Kreskowiak wrote: After you've verified who the command is running as, you can alter your command
line to launch the SC command and have to command prompt stick around:
.Start("CMD", "/K <your entire SC command line here>")
I will try this.
|
|
|
|
|
So I tried the CMD /K WHOAMI and got the non-impersonated user. If I try using the overload of .Start() that has a username & password, I get an Access Denied exception (even when using my current credentials). When I do CMD /K <my sc="" command="" line="">, I also get access denied. I think however the cmd tests are invalid tests because when I do a RunAs impersonatedusername / impersonateduserpassword, it works correctly, but that command prompt window can't do a lot of things. Like it can't interact with the desktop for example.
I have verified the sc command line via a variable as you suggested and it is correct. I even copy and pasted it into the run as'ed command window to make sure I didn't miss some small thing and it worked. If I run it via the Start, the window flashes too fast to see. If I run it via the cmd /k, the window stays around, but I get an access denied.
Not sure whats going on ![Confused | :confused:](https://www.codeproject.com/script/Forums/Images/smiley_confused.gif)
|
|
|
|
|
SledgeHammer01 wrote: I think however the cmd tests are invalid tests because
Nope. You're running a command line app and the command prompt is telling you who it's running as. If the user isn't what you expected it to be, well, that's a problem in your code, not the test. This is telling you who the SC command is running as. If that account doesn't have the appropriate permissions to the target machine to start and stop services, it's going to fail.
SledgeHammer01 wrote: but that command prompt window can't do a lot of things
Such as?? Oh, let me remind you that that statement has absolutely nothing to do with running a command line app, like SC!!
SledgeHammer01 wrote: I even copy and pasted it into the run as'ed command window to make sure I
didn't miss some small thing and it worked.
That command ran as YOUR account. All it does is veryify the command is correct, NOT that it's going to work under the account your code is using (you mentioned impersonation) or the Start method you're calling is using (you said you used one of the overloads that takes a username and password).
SledgeHammer01 wrote: If I run it via the cmd /k, the window stays around, but I get an access
denied.
This is because the command prompt you launched isn't running as the user you think it is. I already told you how to find out what the command you launch with Start is running as. It's simple really. "Access denied" means the account you launched the command with doesn't have permissions to do what you want.
|
|
|
|
|
Dave Kreskowiak wrote: Nope. You're running a command line app and the command prompt is telling you
who it's running as. If the user isn't what you expected it to be, well, that's
a problem in your code, not the test. This is telling you who the SC command is
running as. If that account doesn't have the appropriate permissions to the
target machine to start and stop services, it's going to fail.
Ok Mr. Smarty Pants (j/k)... explain this one... I have just proved again that the impersonation code I am using is working:
using (new Impersonator(_strDomain, _strUsername, _strPassword))
{
System.Diagnostics.Debug.WriteLine(System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString());
System.Diagnostics.Process.Start("CMD", "/K WHOAMI");
}
I have just conducted two tests there... your CMD /K WHOAMI (which returns the wrong non-impersonated logged on user) and WindowsIdentity.GetCurrent() (which CORRECTLY returns the impersonated user!)
I am running on Windows 7 as an admin on my box (but not the remote box), UAC is disabled. So that block of code *is* running as the impersonated user, but Process.Start() seems to be running as non impersonated currently logged on user.
|
|
|
|
|
If you're going to use Process.Start, the ONLY thing that matters is what the CMD window is using.
The impersonation code that you're using does NOT affect the process you launch with Start. The only thing that changes that is using the Start overload that accepts a username and password.
I'm not the "Smarty Pants" here. The CMD prompt is telling you exactly what you need to know and you're ignoring it! That little window is telling you that using the Impersonator class has no effect on which account another process is launched as.
|
|
|
|
|
Dave Kreskowiak wrote: The impersonation code that you're using does NOT affect the process you launch
with Start. The only thing that changes that is using the Start overload that
accepts a username and password. I'm not the "Smarty Pants" here.
The CMD prompt is telling you exactly what you need to know and you're ignoring
it! That little window is telling you that using the Impersonator class has no
effect on which account another process is launched as.
Ok, that makes sense. I guess the methods that ARE working under impersonation are File.Copy() and ServiceController which will run under impersonation.
Kind of weird though, I'm launching PSKILL using Process.Start() and that is working, but I'm using both the impersonation and the built in username & password thing... seems like that one required both... if I just had one or the other, it wouldn't work.
Regardless of all that, obviously, yeah, I gotta get Start() working with the username & password... this is my code for that:
System.Security.SecureString ss = new System.Security.SecureString();
foreach (char ch in _strPassword)
ss.AppendChar(ch);
System.Diagnostics.ProcessStartInfo si = new System.Diagnostics.ProcessStartInfo("cmd.exe");
si.UseShellExecute = false;
si.RedirectStandardInput = true;
si.RedirectStandardError = true;
si.RedirectStandardOutput = true;
si.UserName = _strUsername;
si.Password = ss;
si.Domain = "xxx"; // obviously censored for the forums
si.Arguments = "/K";
System.Diagnostics.Process.Start(si);
This gets a:
An unhandled exception of type 'System.ComponentModel.Win32Exception' occurred in System.dll
Additional information: Access is denied
|
|
|
|
|
HOLY BAJESUS... 3 or 4 days on this and finally solved the problem... changed so many things not sure which one in particular did it... but I think the main culprit was moving the function call outside of the using (Impresonator) block... the two interfere for some reason even though they use the same exact creds.
|
|
|
|
|
Your command string evaluates as sc\\strMachine config . You need at least one space between sc and \\ .
Use the best guess
|
|
|
|
|
It does? How do you figure?
System.Diagnostics.Process.Start("sc", "\\\\" + strMachine + " config \"<the service name>\" start= demand");
The first param is "sc" and then there's a comma there and the second param is the argument string.
|
|
|
|
|
SledgeHammer01 wrote: How do you figure? Easy: epic fail on my part.
However, I do agree with Dave K's suggestion that you build your parameters into a variable so you can see exactly what is being sent to the command processor.
Use the best guess
|
|
|
|
|
There is no overload of Process.Start that allows the executable filename and arguments to be combined into one string. I suspect that you'll find that the documentation[^] will be a great help in your endeavours.
[EDIT] Sorry ignore this, I've just looked at your code again and see that I can't read!
Alan.
|
|
|
|
|
It does? How do you figure?
System.Diagnostics.Process.Start("sc", "\\\\" + strMachine + " config \"<the service="" name="">\" start= demand");
The first param is "sc" and then there's a comma there and the second param is the argument string.
|
|
|
|
|
Sorry for the late response. I think there an old carpenter's adage which goes something like "measure twice and cut once". As I hadn't spotted that comma I guess I should have read twice and then not answered at all!
Alan.
|
|
|
|
|
The applications I write typically involve a lot of data entry, for use in a warehouse/manufacturing environment. Sometimes there can be many different fields, sometimes not so much. But I've always found it a bit tedious and time consuming to restore the UI to its initial state when the user saves an entry, for example.
I mean, a form could have buttons that are disabled initially, a few entry fields that are disabled at first waiting for other input, several input fields that need to be cleared, etc. What is the best method to go about resetting a form once the user is done? I've always just used "thisField.Enabled = false;" and "thatField.Text = string.Empty;" and so on. But is there a more efficient method for achieving this?
djj55: Nice but may have a permission problem
Pete O'Hanlon: He has my permission to run it.
|
|
|
|
|
Replacing the form with a new instance would be a shortcut to "restore" the initial state.
|
|
|
|
|
I could have clarified "form", since I'm referring to WinForms applications. "Form" in this context was actually meant as an input form, not the window itself. But I think I can follow that same concept. I'll give it a try.
djj55: Nice but may have a permission problem
Pete O'Hanlon: He has my permission to run it.
|
|
|
|
|
Oh duh... OK...
You can reset a form...
myForm.Controls.Clear();
myForm.InitializeComponent();
|
|
|
|
|
Thank you, I'll give this a try. Very simple and seems like it should do exactly what I need.
djj55: Nice but may have a permission problem
Pete O'Hanlon: He has my permission to run it.
|
|
|
|
|
The only problem with doing that is that if your form code maintains a state it's not going to get reset. It'll only destroy and recreate the controls to however you had them set in the Form Designer and property settings.
|
|
|
|
|
But isn't that what he wants? Instead of "clearing" everything, which sets textboxes to empty string and whatnot, I thought he wants the "default" values from the form designer to show up - otherwise, yeah, you only need to Form.Controls.Clear() and call it good.
|
|
|
|
|
I don't let the controls determine the status of any state machine I've got behind the forms. The state machine determines the state of the controls and the controls reflect that.
I know there are plenty of cases where the app or form is so simple that there is no state machine behind it, but there are too many noobs out there who rely on the controls to "store" data and determine the state of a form or app based on, say, the text of a button, or if it's enabled or not.
That's not the proper way to do it.
|
|
|
|
|
Yeah definitely incorrect designs would make it more tricky, but I get the impression this particular form doesn't have any initial state other than what was set in the designer...
|
|
|
|