I need to execute this command on our remote Skype server:
SEFAUtil.exe /server:lyncserver.domain1.co.uk sip:MySelf#domain.com /addteammember:sip:OtherUser#domain.com /delayringteam:10
which adds a colleague to my team call group.
I am able to run the command on the server itself, and the code below works when sending other commands to that server:
var processToRun = new[] { process };
var connection = new ConnectionOptions();
var wmiScope = new ManagementScope(String.Format("\\\\{0}\\root\\cimv2", LyncServer), connection);
var wmiProcess = new ManagementClass(wmiScope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
var reason = wmiProcess.InvokeMethod("Create", processToRun);
However, when process is the string:
"cmd /c cd /d C:\\Program Files\\Microsoft Lync Server 2013\\ResKit && SEFAUtil.exe /server:lyncserver.domain1.co.uk sip:MySelf#domain.com /addteammember:sip:OtherUser#domain.com /delayringteam:10"
Then the user is not added to the team call group.
I can see that reason contains the uint 0, which usually indicates success - but the actual command is clearly failing.
I also tried adding > C:\users\user.name\desktop\output.txt and 2> C:\users\user.name\desktop\output.txt to the end of the command, but they just created empty text files, so not very useful!
Update
I tried changing the command to the following:
const string LyncServer = "server.domain1.co.uk";
const string ResKitPath = #"C:\Program Files\Microsoft Lync Server 2013\ResKit";
var command = "SEFAUtil.exe /server:{LyncServer} sip:MySelf#domain.com /addteammember:sip:OtherUser#domain.com /delayringteam:10";
var process = $"cmd /c cd /d \"{ResKitPath}\" && {command}";
So that the path containing spaces is double-quoted and the slashes are not being escaped, but with the same results.
Does anyone know of another way of debugging this or retrieving the output for the newly created process?
I've had a similar issue, mine was that the command shell needed to run elevated. SEFA is a bit naff at giving good error messages, and fails silently.
Related
Plan
The plan is to disable and subsequently enable a device from inside a windows forms application. To test the first building block of my plan, I open cmd with admin privileges and the following works perfectly:
> devcon hwids =ports
> devcon hwids *VID_10C4*
> devcon disable *VID_10C4*
> devcon enable *VID_10C4*
I can see the device being disabled and enabled again in device manager.
I can also achieve all of this by putting the commands into a batch file and running it from cmd with admin privileges. The above tells me that my plan is essentially good.
Application
However, what I actually want to do is achieve the same thing from inside a windows forms application:
I've set the following in the app manifest:
requestedExecutionLevel level="requireAdministrator" uiAccess="false"
For the sake of baby steps, I have checked this, just to ensure that there are no stupid mistakes in paths and whatnot. And it works just fine. The log file shows me the expected output from the dir command.
// Build String
string strCmdText =
"'/c cd " + prodPath +
" && dir " +
" > logs\\logFileEnablePrt.txt \"'";
// Run command
var p = new System.Diagnostics.Process();
var psi = new ProcessStartInfo("CMD.exe", strCmdText);
psi.Verb = "runas"; // admin rights
p.StartInfo = psi;
p.Start();
p.WaitForExit();
However, this does not work. It always returns an empty log file and does not change the device as expected:
// Build String
string strCmdText =
"'/c cd " + prodPath +
" && devcon hwids =ports " +
" > logs\\logFileEnablePrt.txt \"'";
// Run command
var p = new System.Diagnostics.Process();
var psi = new ProcessStartInfo("CMD.exe", strCmdText);
psi.Verb = "runas"; // admin rights
p.StartInfo = psi;
p.Start();
p.WaitForExit();
Error from cmd window is :
'devcon' is not recognized as an internal or external command,
operable program or batch file.
What's going on?
The above has me stumped. I've proved the commands work. I've proved my C# code works. But when I join the 2 together, it doesn't work...
NB: My C# program is running on my D: drive, if that makes any difference...
Updates Based on Comments
#Compo
Using your code, it does exactly the same as with mine. I see an empty log file & no changes made to the device. I've altered the /c to /k so I can see what going on the cmd terminal and I see this:
I've even tried your code C:\\Windows\\System32\\devcon hwids =usb pointing directly at devcon. Also tried \devcon.exe for completeness. The inexplicable error is :
I can see the flipping devcon.exe file sitting right there in the folder! Is there any reason it would not recognise it?
Also, with the command as you wrote it, the log file name is actually named logFileEnablePrt.txt'. I agree that your command looks right, so don't ask me why this happens!
#Panagiotis Kanavos
using your code, I get the following error:
This is at the line p.Start();. I tried putting in devcon.exe, and even the whole path (I checked the folder was in my PATH, and it is). Can't get past this. I actually stumbled on that answer you shared and arrived at this brick wall already.
Here is the code works for me, I don't have ports devices so I change it to usb.
public static void Main()
{
string prodPath = #"c:\devcon\x64";
// Build String
string strCmdText =
"/c \"cd /d " + prodPath +
" && devcon hwids =usb " +
" > log.txt \"";
// Run command
var p = new Process();
var psi = new ProcessStartInfo("CMD.exe", strCmdText);
psi.Verb = "runas"; // admin rights
p.StartInfo = psi;
p.Start();
p.WaitForExit();
}
Worked through a few steps and think I may have an answer...
Just specifying devcon fails as expected...windows cant find the exe as the folder it is in is not in the %PATH% variable in windows..
IF I specify the full path however it works...
It wasnt clear from your original code but if your copy of devcon is sitting in either System32 or Syswow directories you may be hitting an emulation issue as well...see here....
EDIT1:: A way to prove this would be to do Direcory.GetFiles(directory containing devcon) and see if the results line up with what you expect
As for passing arguments through to devcon I'd try something like this as opposed to trying to concatenate one giant cmd line..
A similar example but with netstat:
EDIT 2::Another example but with devcon:
The target platform here for the build was x64
EDIT3::
With my application build set to x86:
After working through the answers and comments above, I seem to have something that reliably works, which obviously I'd like to share back for scrutiny and future use.
So, my function ended up looking like this:
private int enablePort(string action)
{
while (true)
{
// Command Arg
string devconPath = #"c:\Windows\SysNative";
string strCmdText =
"'/c \"cd /d \"" +
devconPath +
"\" && c:\\Windows\\SysNative\\devcon " + action + " *VID_10C4* " +
"> \"" + prodPath + "\\logs\\logFileEnablePrt.txt\"\"";
// Process
var p = new Process();
var psi = new ProcessStartInfo()
{
Arguments = strCmdText,
Verb = "runas",
FileName = "CMD.exe",
UseShellExecute = true
};
p.StartInfo = psi;
p.Start();
p.WaitForExit();
// Grab log output
string logPath = prodPath + "\\logs\\logFileEnablePrt.txt";
Console.WriteLine("logPath = " + logPath);
string tempFile = System.IO.File.ReadAllText(logPath);
System.Console.WriteLine("Contents of WriteText.txt = \n{0}", tempFile);
// Check if it worked
var success = false;
if (tempFile.Contains(action))
{
success = true;
return 0;
}
// Error -> Allow user to try again!
if (MessageBox.Show("Was unable to " + action + " Test Jig COM port. Unlug & Replug USB. Check COM port is enabled if not working.", "COM Port Problem", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
{
return -1;
}
}
}
And the calling code was:
this.enablePort("disable");
int milliseconds = 3000;
await Task.Delay(milliseconds);
this.enablePort("enable");
As you can see in the code above, I've logged everything to see what was going on... Stepping through with the debugger, I can now see after the disable:
USB\VID_10C4&PID_EA60\0001 : Disabled
1 device(s) disabled.
And then after the enable:
USB\VID_10C4&PID_EA60\0001 : Enabled
1 device(s) are enabled.
The one extra thing I need to stress is that during testing, I thought I could hook a serial peripheral onto the port and determine whether it could disable and enable successfully by checking the connection. THIS DOES NOT WORK. The above code only works when the port is idle. Perhaps someone who understands the underlying software could hazard an explanation of why this is.
I have written a simple piece of code to try and copy the WebCacheV01.dat file from the Edge Browser, as the fille is locked I am using the VSS commands to do this.
When I run the command manually, from an elevated prompt, it copies the database without any issue. When I try to replicate the command using C#, it errors.
VSS Subsystem Init failed, 0x80042302 Operation terminated with error
-2403 (JET_errOSSnapshotNotAllowed, OS Shadow copy not allowed (backup or recovery in progress)) after 0.47 seconds.
I have run the debugging, line by line and the arguments are correct. I just can't get around the error message.
using (var cmdEsentutl = new Process())
{
cmdEsentutl.StartInfo.FileName = "esentutl";
cmdEsentutl.StartInfo.UseShellExecute = false;
cmdEsentutl.StartInfo.CreateNoWindow = false;
//cmdEsentutl.StartInfo.Arguments = $#"/y /vss {GlobalVariables.edge44HistoryDB}\WebCacheV01.dat /d E:\WebCacheV01.dat";
cmdEsentutl.StartInfo.Arguments = $#"/y {GlobalVariables.edge44HistoryDB}\WebCacheV01.dat /vssrec V01 . /d F:\WebCacheV01.dat";
cmdEsentutl.StartInfo.Verb = "runas";
cmdEsentutl.StartInfo.RedirectStandardError = true;
cmdEsentutl.Start();
cmdEsentutl.WaitForExit();
}
I'm wishing to run a command from C# to a container set up via docker-compose. In Powershell, I run this command and the file is created:
docker-compose exec database sh -c "mysqldump -u((username)) -p((password)) ((databasename)) > /backups/test.sql"
When I run the following code it seems to ignore the environment variables, even though I have them set. It only creates a file named backup.sql and the SQL outputted to the file indicates that no database was selected. I've verified the env variables are set by outputting the last parameters string to the console.
var exportPath = $"/backups/backup.sql {DateTime.Now}";
using (var runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
runspace.SessionStateProxy.Path.SetLocation(Path.GetFullPath(".."));
using (var pipeline = runspace.CreatePipeline())
{
var cmd = new Command("docker-compose");
cmd.Parameters.Add("exec");
cmd.Parameters.Add("database");
cmd.Parameters.Add($"sh -c \"mysqldump - u{GetEnv("MYSQL_USERNAME")} " +
$"-p{GetEnv("MYSQL_PASSWORD")} {GetEnv("MYSQL_DATABASE")} > {exportPath} \"");
pipeline.Commands.Add(cmd);
pipeline.Invoke();
}
}
GetEnv is just a convenience method for Environment.GetEnvironmentVariable
I'm fairly certain that I am not setting the parameters right, but I don't know where to go from here.
I came across to FluentDocker which seems like a nice way to run docker-compose from c#.
Here is an example from the project page:
using (
var container =
new Builder().UseContainer()
.UseImage("kiasaki/alpine-postgres")
.ExposePort(5432)
.WithEnvironment("POSTGRES_PASSWORD=mysecretpassword")
.WaitForPort("5432/tcp", 30000 /*30s*/)
.Build()
.Start())
{
var config = container.GetConfiguration(true);
Assert.AreEqual(ServiceRunningState.Running, config.State.ToServiceState());
}
Disclaimer: I am not affiliated with the project in any way nor have attempted to use it yet.
I gave up and used CliWrap because it is easier to debug. I couldn't figure out how to set the current directory, but fortunately I could modify the rest of the program to look for stuff in the current directory.
using CliWrap;
using CliWrap.Buffered;
var now = DateTime.Now.ToString().Replace("/", "-").Replace(" ", "-");
var exportPath = $"/backups/backup.sql-{now}";
var cmd = $"exec -T database sh -c \"mysqldump -u{GetEnv("MYSQL_USER")} " +
$"-p{GetEnv("MYSQL_PASSWORD")} {GetEnv("MYSQL_DATABASE")} > {exportPath}\"";
Console.WriteLine(cmd);
var result = await Cli.Wrap("docker-compose")
.WithArguments(cmd)
.ExecuteBufferedAsync();
Console.WriteLine(result.StandardOutput);
Console.WriteLine(result.StandardError);
The library can be found here: https://github.com/Tyrrrz/CliWrap
I am attempting to initialize and push an initial commit to GitLab repository using LibGit2Sharp.
if (!Directory.Exists("D:\\GitRepos\\" + repositoryName))
{
Directory.CreateDirectory("D:\\GitRepos\\" + repositoryName);
File.Create("D:\\GitRepos\\" + repositoryName + "\\README.md").Close();
}
Repository.Init("D:\\GitRepos\\" + repositoryName);
using (var repo = new Repository("D:\\GitRepos\\" + repositoryName))
{
repo.Index.Add("README.md");
Signature author = new Signature("user", "user#user.com", DateTime.Now);
Signature committer = author;
repo.Commit("Initial Commit", author, committer);
repo.Network.Remotes.Add("origin", validRepoHttpsUrl);
Remote remote = repo.Network.Remotes["origin"];
var options = new PushOptions
{
CredentialsProvider = (_url, _user, _cred) =>
new UsernamePasswordCredentials {Username = "validuser", Password = "validpassword"}
};
string pushRefSpec = #"refs/heads/master";
repo.Network.Push(remote, pushRefSpec, options);
}
}
The repository is created and initialized locally without issue. The README file is created and added to the repo index and commit succeeds. When I try to push the commit to the remote endpoint I receive an error stating :
"Request failed with status code: 411"
If I put a breakpoint right before the push and set the http.postBuffer for the repo with the following command:
git config http.postBuffer 524288000
I receive a new error when the push executes:
Failed to write chunk footer: The connection with the server was terminated abnormally
I was able to quickly stand up a bitbucket git repo and push to it without any issues, seems that this may be a problem with gitlab.
It looks like this is a known issue for libgit2sharp based on RobertN's comment. https://github.com/libgit2/libgit2sharp/issues/905
I was able to work around this temporarily by handling the push with a git CLI call.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.WorkingDirectory = "D:\\GitRepos\\" + repositoryName;
p.StartInfo.FileName = "git.exe";
p.StartInfo.Arguments = "push -u origin master";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Something to note is that when this is being run as a windows service as local system the call takes 2-3 minutes for a small commit to push. When i switched the service to run as a domain user it is immediate. Also, this only works because I have ssh and proper keys setup on my host, otherwise git would prompt for a username and password. I had to use the SSH URL instead of HTTP as stated in the original question.
I have a C# application calling a bat file:
new string[] { branchName + ".Order", "Order.bak", "Order"}
var arguments = String.Format("\"{0}\"\"{1}\"\"{2}\"\"{3}\"", stringse[0], stringse[1], stringse[2], sqlPath + "\\");
var psi = new System.Diagnostics.ProcessStartInfo(filename)
{
RedirectStandardOutput = true,
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
UseShellExecute = false,
Arguments = arguments
};
Process createDBs = Process.Start(psi);
System.IO.StreamReader myOutput = createDBs.StandardOutput;
while (!createDBs.HasExited)
{
string output = myOutput.ReadToEnd();
LogStep(output);
}
The bat file looks like this:
#echo off
REM ************************************************
REM * RestoreDB script for use by Development Team *
REM ************************************************
#echo %1 %2 %3 %4
#echo Restore of database started...
SQLCMD -S (local) -d Master -i RestoreDB.sql -v varDatabaseName=%1 varDatabaseBackupFileName= %2 varLogicalName= %3 varSQLDataFolder= %4
#echo Restore of database finished...
pause
The Sql script looks receive these parameters like this:
SET #DatabaseName = N'$(varDatabaseName)'
SET #DatabaseBackupFileName = N'$(varDatabaseBackupFileName)'
SET #LogicalName = N'$(varLogicalName)'
SET #SQLDataFolder = N'$(varSQLDataFolder)'
(Can't paste complete code due to security reasons)
Now my problem is that I don't think I'm passing the variables from bat to sql script correctly.
When calling the bat file out of C# it echo's the values
When calling the sql directly out of command prompt it works correctly, so I know my sql script is working:
SQLCMD -S (local) -d Master -i RestoreDB.sql -v varDatabaseName="Piet.Order.Test" varDatabaseBackupFileName="Order.bak" varLogicalName="Order" varSQLDataFolder="C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\"
I don't get any errors back to my C# application, so when running my application it just runs and calls the bat with parameters, the call from bat to sql seems to go wrong.Is it a format problem with my parameters. I tried single quotes '%1' and tried doubele quotes "%1", nothing seems to work.Can anybody shine some light.Any way maybe how I can retrieve the error that is happening with the call to sql
You need to add a space between arguments
var arguments = String.Format("\"{0}\" \"{1}\" \"{2}\" \"{3}\"",
stringse[0], stringse[1], stringse[2], sqlPath + "\\");
In these scenarios (debugging parameters) could be very useful to start the command processor and leave the console window open after the execution of the program
var arguments = String.Format("/K {4} \"{0}\" \"{1}\" \"{2}\" \"{3}\"",
stringse[0], stringse[1], stringse[2], sqlPath + "\\", filename);
and call the command processor in the ProcessStartInfo
var psi = new System.Diagnostics.ProcessStartInfo("cmd.exe")