Solved

Pass a file (containing workstations) into an Array in a Console application

Posted on 2009-04-01
9
448 Views
Last Modified: 2013-12-17
My goal is this. I'm eventually going to have some workstations passed into a Stored Procedure variable, which will in turn, pass that to a Console.exe file as an argument to process a list of workstations to be pinged.
I want to pass a file containing workstations (using ; (semicolon) as the delimiter, as an argument to a Console application. I'm a little bit familiar with the ProcessStartInfo class. Can someone tell me how to setup passing this file to an Array?
Most grateful to anyone and thank you Experts,
Wally
0
Comment
Question by:wally_davis
  • 6
  • 3
9 Comments
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 24043857
You would probably be better simply passing the path to the file rather than trying to pass the file itself and letting the console app read the file and load its contents into an array itself.
0
 

Author Comment

by:wally_davis
ID: 24044075
There is going to be another process that will pass thousands of workstations to an SP variable and when that SP kicks off, it will pass in thousands of workstation names which will in turn initiate my Console app and will need to pass in all of those workstation names to the console as an argument which will then be taken and stored to a ListCollection or an Array to be further processed.
Speaking the SP, How would you pass in all of that data from the SP into a Console app as an Argument?
0
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 24044259
Passing thousands of parameters to a console app will be problematic partly because of the length limit for command line arguments. But trying to invoke a console app from an SP will be problematic in itself because you will need xp_cmdshell which will be disabled on a lot of systems (assuming you are using SQL Server).

You may want to consider having your SP store the workstations in a table and have your console app talk to the database to retrieve them that way.
0
 

Author Comment

by:wally_davis
ID: 24044297
Trust me. I know it sounds crazy. I've done everything short of telling the person they're out of their minds send data to an SP variable. I wanted the data in a Table and they're insistent on doing it the way they want to. It's hell on me and that's why I'm out here on EE looking for some Expert help.
That being said, we can use the xp_cmdshell (believe it or not) so that is an option. We currently use SQL 2005. I need to figure out how to pass this so called file to the Command Line as an argument and have the Console store it into an Array. As AxxBackwards, as this sounds, is it possible and if so, how could I implement it?
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 52

Expert Comment

by:Carl Tawn
ID: 24044424
Its possible up to a point but, as i said earlier, there is a limit on the length of command line arguments which may become an issue for you if try to pass too much.

Having said that, all you need to do is call the command line app from your SP with something like:

    DECLARE @Workstations VARCHAR(MAX);
    SET @Workstations = 'Workstation1,Workstation2,Workstation3';

    DECLARE @CommandLine sysname;
    SET @CommandLine = 'C:\MyConsoleApp.exe "' + @Workstations + '"';

    EXEC xp_cmdshell @CommandLine;

Then as a simple sample console app, this will read in the command line parameter and output each entry to a file:


static void Main(string[] args)

{

    List<string> workstations;
 

    if (args.Length > 0)

    {

        // load command line arg into List<string> assuming comma-seperated values

        workstations = new List<string>(args[0].Split(new char[] { ',' }));
 

        System.IO.StreamWriter sw = new System.IO.StreamWriter("C:\\Ouput.txt");

        foreach (string s in workstations)

            sw.WriteLine(s);
 

        sw.Close();

    }

}

Open in new window

0
 

Author Comment

by:wally_davis
ID: 24044695
Carl,
I'm getting the error "Incorrect syntax near the keyword 'DECLARE'.
See SP code below:

USE DMS

GO
 

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO
 

CREATE Procedure RunPingUtil

  DECLARE @Workstations varchar(max);

  SET @Workstations = 'B001617259BA7,B001E371E21B2,B001422C95811';

								      -- Passing in Wkstn values'
 

DECLARE @CommandLine sysname;

SET @CommandLine = 'C:\Test\ProofOfConcept.exe ''' + @Workstations + '''';
 

EXEC xp_cmdshell @CommandLine;
 

GO

Open in new window

0
 

Author Comment

by:wally_davis
ID: 24046844
Figured it out. I'll get back with results in the a.m. here in Arizona.
0
 

Author Comment

by:wally_davis
ID: 24050274
Carl, Everything is in place. However, when I execute the SP, it's giving me some Security issues. I used xp_cmdshell not too long ago within our Company and I know it still works: Here's the errors below. If you happen to know what the probable cause is that would be great. I'll also post the current code below per your suggestions above and your code at to my C# Code.

NULL
Unhandled Exception: System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
   at System.Threading.ThreadPool.SetMaxThreads(Int32 workerThreads, Int32 completionPortThreads)
   at ProofOfConcept.Program.Main(String[] args)
The action that failed was:
Demand
The type of the first permission that failed was:
System.Security.Permissions.SecurityPermission
The first permission that failed was:
<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Flags="ControlThread"/>
NULL
The demand was for:
<PermissionSet class="System.Security.PermissionSet"
version="1">
<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Flags="ControlThread"/>
</PermissionSet>
NULL
The granted set of the failing assembly was:
<PermissionSet class="System.Security.PermissionSet"
version="1">
<IPermission class="System.Security.Permissions.FileDialogPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Access="Open"/>
<IPermission class="System.Security.Permissions.IsolatedStorageFilePermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Allowed="ApplicationIsolationByUser"
UserQuota="512000"/>
<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Flags="Execution"/>
<IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Window="SafeTopLevelWindows"
Clipboard="OwnClipboard"/>
<IPermission class="System.Security.Permissions.UrlIdentityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Url="file://B001C231FC4CC/c$/Test/ProofOfConcept.exe"/>
<IPermission class="System.Security.Permissions.ZoneIdentityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Zone="Internet"/>
<IPermission class="System.Drawing.Printing.PrintingPermission, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
version="1"
Level="SafePrinting"/>
</PermissionSet>
NULL
The assembly or AppDomain that failed was:
ProofOfConcept, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
The method that caused the failure was:
Void Main(System.String[])
The Zone of the assembly that failed was:
Internet
The Url of the assembly that failed was:
file://B001C231FC4CC/c$/Test/ProofOfConcept.exe
NULL

------------- SP --------------------------

USE DMS

GO
 

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO
 

ALTER Procedure RunPingUtil

AS

BEGIN

	SET NOCOUNT ON;
 

DECLARE @Workstations varchar(max)

SET @Workstations = 'B001617259BA7,B001E371E21B2,B001422C95811'
 

DECLARE @CommandLine sysname

SET @CommandLine = '\\B001C231FC4CC\c$\Test\ProofOfConcept.exe ''' + @Workstations + ''''
 

EXEC xp_cmdshell @CommandLine
 

END

GO

--------------- C# CODE -----------------------------------

using System;

using System.Collections.Generic;

using System.Net;

using System.Net.NetworkInformation;

using System.Data.SqlClient;

using System.Diagnostics;
 

namespace ProofOfConcept

{

    class Program

    {

        // This is not used at the moment... but may be...

        static void UpdateDatabase(Object database)

        {
 

        }
 

        // The threadpool's threads call this with the argument "new "String( node.NodesToPing)" 

        // that is passed to QueueUserWorkItem and so, each computer is pinged quickly in the

        // PingWorkstations() method when added to the threadpool.

        static void PingWorkstations(Object threadContext)

        {

            String computer = (String)threadContext;

            // PingThreadContext pc = (PingThreadContext)threadContext;

            

            string status = "";

            string epAddress = "";
 

            SqlConnection conn = new SqlConnection(SettingsManager.ConnectionString);

            SqlCommand sqlCmd = new SqlCommand("usp_PingStatus", conn);

            sqlCmd.CommandType = System.Data.CommandType.StoredProcedure;
 

            try

            {   

                // Verify host is in DNS first

                IPHostEntry IPHost = Dns.GetHostEntry(computer);
 

                // Ping the workstation, get status and update DB

                foreach (IPAddress address in IPHost.AddressList)

                {

                    Ping p = new Ping();
 

                    try

                    {

                        // Based on the Ping Status will determine which

                        // case to process.

                        PingReply pr = p.Send(computer);

                        switch (pr.Status)

                        {

                            case IPStatus.Success:

                                sqlCmd.Parameters.AddWithValue("Status", "Reachable");

                                sqlCmd.Parameters.AddWithValue("Endpoint", computer);

                                sqlCmd.Parameters.AddWithValue("IPAddress", (address != null) ? address.ToString() : 

                                                                IPAddress.None.ToString());

                                sqlCmd.Parameters.AddWithValue("DTStamp", DateTime.Now);
 

                                status = "Reachable";

                                epAddress = (address != null) ? address.ToString() : IPAddress.None.ToString();

                                //Console.WriteLine(computer + " - Sweet");

                                break;

                            case IPStatus.TimedOut:

                                sqlCmd.Parameters.AddWithValue("Status", "Timed Out");

                                sqlCmd.Parameters.AddWithValue("Endpoint", computer);

                                sqlCmd.Parameters.AddWithValue("IPAddress", (address != null) ? address.ToString() :

                                                                IPAddress.None.ToString());

                                sqlCmd.Parameters.AddWithValue("DTStamp", DateTime.Now);
 

                                status = "Timed Out";

                                epAddress = (address != null) ? address.ToString() : IPAddress.None.ToString();

                                //Console.WriteLine(computer + " - Timedout");

                                break;

                            case IPStatus.DestinationHostUnreachable:

                                sqlCmd.Parameters.AddWithValue("Status", "Host Unreachable");

                                sqlCmd.Parameters.AddWithValue("Endpoint", computer);

                                sqlCmd.Parameters.AddWithValue("IPAddress", (address != null) ? address.ToString() :

                                                                IPAddress.None.ToString());

                                sqlCmd.Parameters.AddWithValue("DTStamp", DateTime.Now);
 

                                status = "Host Unreachable";

                                epAddress = (address != null) ? address.ToString() : IPAddress.None.ToString();

                                //Console.WriteLine(computer + " - Timedout");

                                break;

                            case IPStatus.DestinationNetworkUnreachable:

                                sqlCmd.Parameters.AddWithValue("Status", "Network Unreachable");

                                sqlCmd.Parameters.AddWithValue("Endpoint", computer);

                                sqlCmd.Parameters.AddWithValue("IPAddress", (address != null) ? address.ToString() :

                                                                IPAddress.None.ToString());

                                sqlCmd.Parameters.AddWithValue("DTStamp", DateTime.Now);

                                status = "Network Unreachable";

                                epAddress = (address != null) ? address.ToString() : IPAddress.None.ToString();

                                break;

                            case IPStatus.Unknown:

                                sqlCmd.Parameters.AddWithValue("Status", "unknown");

                                sqlCmd.Parameters.AddWithValue("Endpoint", computer);

                                sqlCmd.Parameters.AddWithValue("IPAddress", "NA");

                                sqlCmd.Parameters.AddWithValue("DTStamp", DateTime.Now);
 

                                status = "unknown";

                                epAddress = "NA";

                                break;

                        }

                    }

                    catch (Exception ex)

                    {

                        Console.WriteLine("Error occurred: " + ex.Message);

                    }
 

                    //Open a DB connection.... SEND THE DATA CLOSE IT
 

                    try

                    {

                        // Lets add the data to the DB

                        conn.Open();

                        sqlCmd.ExecuteNonQuery();

                        Console.WriteLine("EP Status : {0} \nEP Name: {1} \nEP Address: {2}\n", status, computer, address );

                    }

                    catch

                    {

                    }

                    finally

                    {

                        conn.Close();

                    }

                }

            }

            // If no DNS Record exists then update

            // Endpoint information in nodes table

            catch

            {
 

                sqlCmd.Parameters.AddWithValue("Status", "No DNS Record");

                sqlCmd.Parameters.AddWithValue("Endpoint", computer);

                sqlCmd.Parameters.AddWithValue("IPAddress", "NA");

                sqlCmd.Parameters.AddWithValue("DTStamp", DateTime.Now);
 

                status = "No DNS Record";

                epAddress = "NA";
 

                conn.Open();

                sqlCmd.ExecuteNonQuery();

                Console.WriteLine("EP Status : {0} \nEP Name: {1} \nEP Address: {2}\n", status, computer, epAddress);

                conn.Close();
 

            }

        }
 

        /* When availThreads = maxThreads the 

         * entire ThreadPool has completed being

         * processed and a Sleep of 1 second before

         * the next ThreadPool starts processing

         */

        static void WaitForPool()

        {

            int maxThreads = 0;

            int placeHolder = 0;

            int availThreads = 0;

            while (true)

            {

                System.Threading.ThreadPool.GetMaxThreads(out maxThreads, out placeHolder);

                System.Threading.ThreadPool.GetAvailableThreads(out availThreads, out placeHolder);

                if (availThreads == maxThreads) break;

                System.Threading.Thread.Sleep( 1000 );                

            }
 

            return ;

        }

        /* -----------------------------   Main () Program entry ------------------------------ */
 

        // This is the Collection List property

        // that will hold each workstation value

        // that will eventually get pinged.

        public string nodeToPing;

        public string NodeToPing

        {

            get { return nodeToPing; }

            set { nodeToPing = value; }

        }
 
 

        static void Main(string[] args)

        {
 

            // Do Database Query Here.....

            // This will hold the entire workstation 

            // list that is pulled from the Nodes table

            List<Program> nodeList = new List<Program>();

            List<string> workstations;

            

            if (args.Length > 0)

            {

                // Load command line arg into List<string> collection

                // assuming comma-seperated values

                workstations = new List<string>(args[0].Split(new char[] { ',' }));

                foreach (string wkstn in workstations)

                {

                    Program node = new Program();

                    node.NodeToPing = wkstn;

                    nodeList.Add(node);

                }
 

            }
 

                if (nodeList.Count > 0)

                {

                    // parameters( max # of worker threads in thread

                    // pool and max # asynchronous IO threads in pool)

                    System.Threading.ThreadPool.SetMaxThreads(65, 10);

                    System.Threading.ThreadPool.SetMinThreads(65, 10);
 

                    /* For each computer in the computer list,

                     * each computer to be pinged by the PingWorkstations()

                     * method gets passed to the QueueUserWorkItem to be

                     * processed by the threadpool thread. 

                     * Each workstation to be pinged gets added to the pool

                     * and processed quickly.

                     */

                    foreach (Program node in nodeList)

	                {

                		System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(PingWorkstations), node.NodeToPing );

	                }

                }
 

                /* This little baby is the "ShamWow" it waits till all those threads in the threadpool 

                * are done... and you will say "Wow" everytime.

                * It's made in Germany, lol. This method processes and completes each threadpool before 

                * moving onto the next threadpool.

                */

                WaitForPool();

            }

        }

    }

Open in new window

0
 

Accepted Solution

by:
wally_davis earned 0 total points
ID: 24063448
This question was answered in combination with two previous threads I had Carl working on so and has now been resolved. This one can be closed as it was a redundant question.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Visual Studio Code with .Net Core 5 16
Expando 4 34
Open form in the top right hand corner of screen 5 20
Showdialog 8 20
Summary Displaying images in RichTextBox is a common requirement with limited solutions available. Pasting through clipboard or embedding into RTF content only support static images.  This article describes how to insert Windows control objects int…
For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now