Automating IISRESET via remote desktop connection after a TFS build - c#

I want to automate a process, which is invoked after a successful build on TFS. The process will RDP to a test server, then call a C# application on that server, and reset IIS on that server. Each step will return the result so whether or not to call next step is based on the previous step.
There are a few obstacles in implementing it. Below is what I want to know if it is possible, and how to code it.
1) Invoking the process via a build on TFS
There is an option in Build definition to invoke automated test. I assume that the process can be invoked by implementing it as a test.
2) RDP to remote server
I found the links below, which might be a solution
Process rdcProcess = new Process();
rdcProcess.StartInfo.FileName = Environment.ExpandEnvironmentVariables(#"%SystemRoot%\system32\cmdkey.exe");
rdcProcess.StartInfo.Arguments = "/generic:TERMSRV/192.168.0.217 /user:" + "username" + " /pass:" + "password";
rdcProcess.Start();
rdcProcess.StartInfo.FileName = Environment.ExpandEnvironmentVariables(#"%SystemRoot%\system32\mstsc.exe");
rdcProcess.StartInfo.Arguments = "/v " + "192.168.0.217"; // ip or name of computer to connect
rdcProcess.Start();
Run mstsc.exe with specified username and password
Automating remote desktop connection
3) IISReset
I think it should be simply invoke "IISRESET" after RDP, but the problem is that, HOW to captrue the result of running IISRESET.
The tools that might be suitable are:
1) Powershell - I don't know much about Powershell but am willing to learn if required
2) C#
My question is that how to implement it, any code example, and idea would be very much appreciated.

Check my answer here which is somewhat related: Answer
If the user which runs the TFSBuild Service on the build server have enough rights on the test server then you can use psexec or powershell to run your commands remotely. Read the below links:
PSEXEC
PowerShell Remote commands
There is no inbuilt activity/process which can help you run scripts on remote machines in TFS build workflow.
Step 1 for you is to identify how you are going to run scripts on the remote machine, as mentioned above you can either use PSEXEC or Powershell (though running PowerShell on remote computers may be a little more complicated to set up).
Step2, write the actual scripts to do the work, stop services, install MSI etc.
Step3, Edit your current build defintion - create a new custom activity or make use of InvokeProcess activity from within your build definition to invoke the script that you have created in Step 2. InvokeProcess Activity

in most cases you do not need to run iisreset
if you want to upgrade an asp.net application, try to put app_offline.htm in the application folder, it will stop an application and application files will be unlocked
after upgrading an application, it will restart automatically, or you can "touch" web.config to force restart

You might be better using the Lab Build to run the scripts as part of an environment ob the target computer. It can run any powershell against that machine as well as deploy and execute applications....

Question: HOW to capture the result of running IISRESET
I believe the old fashioned way, Hope this is what you are looking for
c:> IISRESET >> C:\temp.log
You can use the above either from CMD or powershell

In the past I have used Psexec to run commands against a remote server and where ever we need to control flow on the result of that command, we simply piped the console out to a shared folder and checked for our success flag.
I am not sure if TFS can run commands in this manner but we implemented it on hudson/jenkins.
This won't answer your question directly but it may offer a better way forward
An Example:
psexec.exe \remoteserver "iisreset > h:\iisreset.log"
Then run a grep or similar against the iisreset.log with your success flag as a condition to run the next step.

Related

SQL job does not open cmd

I have an SSIS package which has a script task that executes a program via cmd promt.
The task runs fine when I execute the package from the integrated service catalog however when I run it as part of a sql server agent job the job reports successful but it does not do anything.
It’s almost a if the task does not execute at all, because when I run the package via the ssis catalog I get a cmd popup with a log of the what’s happening, where as when I run it via the job I don’t get this cmd pop up.
I’m suing sql server 2016 and the job is run with a proxy user account.
#PanagiotisKanavos has likely hit the nail on the head. Script Tasks have a Read Only Variable available to them System::InteractiveMode You can check the value of that Variable within a Script task to determine whether the process can communicate with the desktop aka "someone's at the wheel."
If you attempt to interact with the desktop from a job, the Script Task should throw an Error. For bonus points, an account can be marked in Active Directory as ... denied desktop or something like that which even if you wanted to run a job in some interactive mode, you won't be able to.
Within my Script Tasks, if I have the possibility of opening windows as you describe, I always wrap it in a logic block like
string message = "Some diagnostic message";
if ((bool)this.Dts.Variables["System::InteractiveMode"].Value)
{
MessageBox.Show(message);
}
Sample of the code running for a different purpose is on my blog
http://billfellows.blogspot.com/2015/02/is-my-ssis-package-running-in-32-or-64.html
And likely duplicates
https://stackoverflow.com/a/17282654/181965
https://stackoverflow.com/a/43371495/181965

Start Node.js server from a C# Application

A requirement has arisen that I need to start a Node.js server from a C# application, this is as simple as running a server.js script within the Node.js console. However, I'm not entirely certain how exactly to achieve that.
Here's what I've looked into so far:
In the Node.js installation, there's a file called C:\Program Files (x86)\nodejs\nodevars.bat, this is the command prompt window for Node.js. To start the server, I could possibly be using the following steps:
Execute the nodevars.bat file.
SendKeys to the new process console window to start the server.
This approach feels a bit fragile. There's no guarantee that the target user will have their Node.js installation in the same place, also sending keys to a process may not be an ideal solution.
Another method could be:
Write a batch file that executes nodevars.bat.
Execute the batch file from the C# application.
This seems like a better approach. However, the only problem here is that the nodevars.bat opens in a new console window.
So to the question(s), is there a way I can start a node.js server script using functionality built into the node.js installation? Perhaps sending arguments to the node.exe?
If it is to serve multiple users, i.e. as a server, then you can use the os-service package, and install a Windows service. You can then start and stop the service using the standard API.
If you are to start the server as a "single purpose" server, i.e. to serve only the current user, then os-service is the wrong approach. (Typically when using this approach you will specify a unique port for the service to use, which will only be used by your application).
To start a batch file or other Console application, from C#, without showing a console window, use the standard method, but be sure to specify:
ProcessStartInfo psi = new ProcessStartInfo();
psi.UseShellExecute = false; // This is important
psi.CreateNoWindow = true; // This is what hides the command window.
psi.FileName = #"c:\Path\to\your\batchfile.cmd";
psi.Arguments = #"-any -arguments -go Here"; // Probably you will pass the port number here
using(var process = Process.Start(psi)){
// Do something with process if you want.
}
There are a few different ones but I recommend the os-service package.

Run a DOS command in .NET

I have a set of commands like:
C:
cd Project
testproj.exe
My system gets these commands one by one from a remote system.
I need to execute each command in cmd.exe on receiving the command from the remote system. How to execute these using .NET?
I also need to return the result of testproj.exe to the remote machine. How to take the result after running command?
Process.Start cmd.exe, and hook StandardIn, StandardOut, and StandardError. Then, when a command comes in, just write it to StandardIn and read StandardOut/Error for the return. The whole thing shouldn't be more than 15 LOC.
That being said, just installing the Telnet Server would probably be easier - as it sounds like that's what you're essentially replicating....
var process = System.Diagnostics.Process.Start( "testproj.exe" );
process.WaitForExit();
var result = process.ExitCode;
This won't really honor things like "C:" or "CD path". Instead you'd want to create a batch file in a temporary folder then call the batch file.
Take a look at System.Diagnostics.Process. You can redirect stdout/stderr somewhere to get the output.
The C: and cd Project operations can be done inside the lanching application using the Directory class using the SetCurrentDirectory method.
Then just use the Process class to launch the testproj.exe executable.
Instead of trying to support all the commands of DOS, just have a small subset implemented which will guarantee nothing can go wrong. Like Don't allow DELETE, RD, FORMAT etc.
So, basically you would only have a subset of DOS commands. Once you have the command set, you can code for those specific commands using a extension mechanisms or as pluggable modules.
This will also helps you safe guard your machine from malicious attacks and worst to happen is there could be data sent out but from machine, the data / system can never be harmed.
UPDATE: The implementaion of specific commands is left to you. You could use .NET API or have System.Diagnostics.Process

Canceling a programatically started SQL Server Express Install

During my application setup, the user has the option of installing a new SQL Server Express 2005 instance in the local machine if they don't want to use an already existing SQL Server 2005 in their network for whatever reason.
As the SQL Server installation is optional, I don't have it as a prerequisite of my installer. Instead, I just bundle the sqlexpr32.exe setup in my install media and programatically launch it with the appropriate command line arguments in order to perform an automatic install. (Note: I'm using the /qb command line flag so the install is not silent, it shows the user interface, but does not ask for any user input). And in case anyone wants to know, I'm following this Microsoft article on how to launch the SQL Server Express setup.
This is what I'm doing in my custom install action:
// All this runs on a background thread so the user
// can cancel my app's setup at any time
// Launch the installer
Process setupProcess = new Process();
setupProcess.StartInfo.FileName = "sqlexpr32.exe";
setupProcess.StartInfo.Arguments = " a bunch of command line args here";
setupProcess.StartInfo.UseShellExecute = false; // to avoid a shell window
setupProcess.Start();
// At this point the SQL Server installer is running
// Monitor the process on 2-second intervals:
while (!setupProcess.WaitForExit(2000))
{
if(WasCancelled) // flag that is set when the user cancels my app's setup
{
// This following line is my problem. Sending CloseMainWindow does not
// seem to work. The SQL Server installer just keeps running.
setupProcess.CloseMainWindow();
setupProcess.WaitForExit();
break;
}
}
// After this point I build a results report for the user.
// My app's installer does not yet quit even if it was canceled.
So my question is: How could I 'signal' the SQL Server installer process to cancel and exit?
This line does not seem to do anything:
setupProcess.CloseMainWindow();
This also does not work:
setupProcess.Close(); // This closes my handle. Not the target process.
And I obviously wouldn't want to just kill the process as I could be leaving the user's machine in a not-so-desirable state, in the best case with a lot of garbage files or worse, with a corrupt install.
Any ideas? Sending keys or simulating user clicks? Or hopefully something less hacky?
EDIT:
I think I have found out why CloseMainWindow does not work:
The process I start (sqlexpr32.exe) is not really the one that shows the UI for the SQLServer Installer, but a self-extracting exe that in turn launches the sql server real setup.exe as a child process. So this issue gets even harder. =(
What if you wait until the installer finishes, and after that - if the user has cancelled the main process - you uninstall it immediately?
I know it's a more time consuming process but it's clear and easy.

Best way to run a tool from ASP.Net page

I have a developer tool that I want to run from an internal site. It scans source code of a project and stores the information in a DB. I want user to be able to go to the site, chose their project, and hit run.
I don't want the code to be uploaded to the site because the projects can be large. I want to be able to run my assembly locally on their machine. Is there an easy way to do this?
EDIT: I should note, for the time being, this needs to be accomplished in VS2005.
EDIT 2: I am looking for similar functionality to TrendMicro's Housecall. I want the scan to run locally, but the result to be displayed in the web page
You could use a ClickOnce project (winform/wpf) - essentially a regular client app, deployed via a web-server. At the client, it can do whatever it needs. VS2005/VS2008 have this (for winform/wpf) as "Publish" - and results in a ".application" file that is recognised by the browser (or at least, some browsers ;-p).
You might be able to do the same with Silverlight, but that has a stricter sandbox, etc. It would also need to ask the web-server to do all the db work on its behalf.
I want to be able to run my assembly
locally on their machine
Sounds like you want them to download the tool and run it from their local machine, does that work for you?
Any code can scan files given the location and permissions. For a website to open an exe on a different machine and permit that to run and get access to the files contained on the web server would require a horrifically low level of security that would mean the entire system is practically completely open to attack. If your system is completely behind a firewall and hence protected from outside intererance then you want to look more at the permissions and less at the code.
To run an exe on a machine try following notepad example, though you may have to use a specified directory as well
ProcessStartInfo psi = new ProcessStartInfo("notepad.exe");
psi.WindowStyle = ProcessWindowStyle.Hidden;
Process p = new Process();
p.EnableRaisingEvents = true;
p.Exited += new EventHandler(ExitHandlerToKillProcess);
p.StartInfo = psi;
p.Start();
and when done dont forget to kill the Process. Alternately use javascript. Either way watch the security permissions and remember the risks of doing this.
I would probably write some sort of command line tool or service that does the processing and extraction of project data. Then I would use a page to update/register projects that the web server and the command line tool both have common access to. then at specified times either manually or via cron or similar mechanisms extract the data to your database. once you have this, you just use the website to display last extraction times and the extracted data.
if the projects/end users are on a different subnet etc, then you will need the end users to run the tool and then have it post the data into the database.

Categories

Resources