ArcObjects Library Reference  

ISConfig

About the Publish an image service and set configurations Sample

[C#]

ISConfig.cs

using System;
using System.IO;
using ESRI.ArcGIS;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Server;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.DataSourcesRaster;
namespace ISConfig
{
    /// <summary>
    /// 1. Description:
    /// This sample demonstrate how to create an image service and set configurations based on data source types (raster dataset, mosaic dataset, compiled image service definition, raster layer); it also have additional features to start,stop,delete image service programmatically.
    /// The user running this utility needs to be in the agsadmin group on ArcGIS Server; and needs access to data source.
    /// The application can be run locally on AGSServer machine (localhost), or remotely. If source data is iscdef, image server must be already registered on ArcGIS Server.
    /// 2. Case sensitivity:  
    /// (1) switches are case sensitive. 
    /// (2) when publish a service, the service name is case sensitive
    /// e.g. If it's published to a folder, e.g. Temporary/Test1. "Temporary" must match the case.
    /// 3. Usage:
    /// Run from command line environment. Usage. <>: required parameter; |: pick one.
    /// isconfig -o publish -h <host> -d <datapath> -n <configName>
    /// isconfig -o <delete|start|stop|pause> -h <host> -n <configName>
    /// isconfig -o <list> -h <host>
    /// Example 1: isconfig -o publish -h localhost -d \\myserver\data\test.gdb\mdtest -n mdtest
    /// Example 2: isconfig -o stop -h myservername -n mdtest
    /// Example 3: isconfig -o list -h myservername
    /// </summary>
    class ISConfig
    {
        #region static variables
        private static string sourcePath = ""; //data source path: a raster dataset, an iscdef, a mosaic dataset
        private static string host = ""; //host machine; use "localhost" for local ags server
        private static string configName = ""; //image service configuration name
        private static IGISServerConnection2 gisServerConnection = null;
        private static IRasterDataset rasterDataset = null;

        #endregion

        [STAThread]
        public static void Main(string[] args)
        {
            try
            {
                //validation
                if (!ValidateParams(args))
                    return;
                //license           
                if (!InitLicense())
                    return;
                //retrieve parameters
                Retrieve_Params(args);
                string operation = args[1];
                switch (operation.ToLower())
                {
                    case "publish":
                        CreateISConfig();
                        break;
                    case "delete":
                        DeleteService();
                        break;
                    case "start":
                        StartService();
                        break;
                    case "stop":
                        StopService();
                        break;
                    case "pause":
                        PauseService();
                        break;
                    case "list":
                        ListServices();
                        break;
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine("Error: {0}", exc.Message);
            }
        }


        #region management operations
        /// <summary>
        /// create image service configuration
        /// </summary>
        private static void CreateISConfig()
        {
            try
            {
                if (!ConnectAGS(host)) return;
                esriImageServiceSourceType sourceType = GetSourceType(sourcePath);
                //connect to ArcGIS Server and create configuration
                IGISServerConnection gisServerConnection = new GISServerConnectionClass();
                gisServerConnection.Connect(host);
                IServerObjectAdmin soAdmin = gisServerConnection.ServerObjectAdmin;
                IServerObjectConfiguration soConfig = (IServerObjectConfiguration)soAdmin.CreateConfiguration();

                //set general service parameters
                soConfig.Name = configName;
                soConfig.TypeName = "ImageServer";
                soConfig.StartupType = esriStartupType.esriSTAutomatic;
                soConfig.IsPooled = true;
                soConfig.IsolationLevel = esriServerIsolationLevel.esriServerIsolationHigh;
                soConfig.MinInstances = 1;
                soConfig.MaxInstances = 2;
                IPropertySet propertySet_Recycle = soConfig.RecycleProperties;
                propertySet_Recycle.SetProperty("Start", "00:00");
                propertySet_Recycle.SetProperty("Interval", "86400");
                IPropertySet propertySet = soConfig.Properties;
                if (sourceType == esriImageServiceSourceType.esriImageServiceSourceTypeCatalog)//(sourceDataPath.ToLower().EndsWith(".iscdef"))
                    propertySet.SetProperty("ServiceDefinition", sourcePath);
                else
                    propertySet.SetProperty("Path", sourcePath);
                propertySet.SetProperty("SupportedImageReturnTypes", "URL");

                //virtual directory
                IEnumServerDirectory dirs = soAdmin.GetServerDirectories();
                dirs.Reset();
                IServerDirectory serverDir = dirs.Next();
                while (serverDir != null)
                {
                    if (((IServerDirectory2)serverDir).Type == esriServerDirectoryType.esriSDTypeOutput)
                    {
                        propertySet.SetProperty("OutputDir", serverDir.Path);
                        propertySet.SetProperty("VirtualOutputDir", serverDir.URL);
                        break;
                    }
                    serverDir = dirs.Next();
                }


                //properties for a mosaic dataset;
                if (sourceType == esriImageServiceSourceType.esriImageServiceSourceTypeMosaicDataset)
                {
                    IFunctionRasterDataset functionRasterDataset = (IFunctionRasterDataset)rasterDataset;
                    IPropertySet propDefaults = functionRasterDataset.Properties;
                    propertySet.SetProperty("MaxImageHeight", propDefaults.GetProperty("MaxImageHeight"));//4100
                    propertySet.SetProperty("MaxImageWidth", propDefaults.GetProperty("MaxImageWidth"));//15000
                    propertySet.SetProperty("AllowedCompressions", propDefaults.GetProperty("AllowedCompressions"));//"None,JPEG,LZ77"
                    propertySet.SetProperty("DefaultResamplingMethod", propDefaults.GetProperty("DefaultResamplingMethod"));//0
                    propertySet.SetProperty("DefaultCompressionQuality", propDefaults.GetProperty("DefaultCompressionQuality"));//75
                    propertySet.SetProperty("MaxRecordCount", propDefaults.GetProperty("MaxRecordCount"));//500
                    propertySet.SetProperty("MaxMosaicImageCount", propDefaults.GetProperty("MaxMosaicImageCount"));//20
                    propertySet.SetProperty("MaxDownloadImageCount", propDefaults.GetProperty("MaxDownloadImageCount"));//20
                    propertySet.SetProperty("AllowedFields", propDefaults.GetProperty("AllowedFields"));//"Name,MinPS,MaxPS,LowPS,HighPS,CenterX,CenterY"
                    propertySet.SetProperty("AllowedMosaicMethods", propDefaults.GetProperty("AllowedMosaicMethods"));//"Center,NorthWest,LockRaster,ByAttribute,Nadir,Viewpoint,Seamline"
                    propertySet.SetProperty("AllowedItemMetadata", propDefaults.GetProperty("AllowedItemMetadata"));//"Full"
                    //propertySet.SetProperty("DownloadDir", ""); //put the download dir here
                    //propertySet.SetProperty("VirutalDownloadDir", ""); //put the virtual download dir here
                }
                else if (sourceType != esriImageServiceSourceType.esriImageServiceSourceTypeCatalog) //not iscdef
                {
                    propertySet.SetProperty("MaxImageHeight", 4100);
                    propertySet.SetProperty("MaxImageWidth", 15000);
                    propertySet.SetProperty("AllowedCompressions", "None,JPEG,LZ77");
                    propertySet.SetProperty("DefaultResamplingMethod", 0);
                    propertySet.SetProperty("DefaultCompressionQuality", 75);
                }

                //enable web capabilities
                IServerObjectConfiguration2 soConfig2 = (IServerObjectConfiguration2)soConfig;
                soConfig2.Info.SetProperty("WebEnabled", "true");
                if (sourceType == esriImageServiceSourceType.esriImageServiceSourceTypeMosaicDataset)
                    soConfig2.Info.SetProperty("WebCapabilities", "Image,Catalog,Metadata,Download,Pixels");
                else
                    soConfig2.Info.SetProperty("WebCapabilities", "Image,Metadata");

                //enable wcs, assume data has spatial reference
                soConfig2.set_ExtensionEnabled("WCSServer", true);
                IPropertySet propertySetWCS = soConfig2.get_ExtensionInfo("WCSServer");
                propertySetWCS.SetProperty("WebEnabled", "true");


                //enable wms
                soConfig2.set_ExtensionEnabled("WMSServer", true);
                IPropertySet propertySetWMS = soConfig2.get_ExtensionInfo("WMSServer");
                propertySetWMS.SetProperty("WebEnabled", "true");

                //add configuration and start
                soAdmin.AddConfiguration(soConfig);
                soAdmin.StartConfiguration(configName, "ImageServer");

                if (soAdmin.GetConfigurationStatus(configName, "ImageServer").Status == esriConfigurationStatus.esriCSStarted)
                    Console.WriteLine("{0} on {1} has been configured and started.", configName, host);
                else
                    Console.WriteLine("{0} on {1} was configured but can not be started, please investigate.", configName, host);
            }
            catch (Exception exc)
            {
                Console.WriteLine("Error: {0}", exc.Message);
            }
        }

        /// <summary>
        /// delete a service
        /// </summary>
        private static void DeleteService()
        {
            try
            {
                if (!ConnectAGS(host)) return;
                IServerObjectAdmin soAdmin = gisServerConnection.ServerObjectAdmin;
                if (!ValidateConfigName(soAdmin, ref configName, host)) return;
                soAdmin.DeleteConfiguration(configName, "ImageServer");
                Console.WriteLine("{0} on {1} was deleted successfully.", configName, host);
            }
            catch (Exception exc)
            {
                Console.WriteLine("Error: {0}", exc.Message);
            }
        }

        /// <summary>
        /// start a service
        /// </summary>
        private static void StartService()
        {
            try
            {
                if (!ConnectAGS(host)) return;
                IServerObjectAdmin soAdmin = gisServerConnection.ServerObjectAdmin;
                if (!ValidateConfigName(soAdmin, ref configName, host)) return;
                soAdmin.StartConfiguration(configName, "ImageServer");
                if (soAdmin.GetConfigurationStatus(configName, "ImageServer").Status == esriConfigurationStatus.esriCSStarted)
                    Console.WriteLine("{0} on {1} was started successfully.", configName, host);
                else
                    Console.WriteLine("{0} on {1} couldn't be started, please investigate.", configName, host);
            }
            catch (Exception exc)
            {
                Console.WriteLine("Error: {0}", exc.Message);
            }
        }

        /// <summary>
        /// stop a service
        /// </summary>
        private static void StopService()
        {
            try
            {
                if (!ConnectAGS(host)) return;
                IServerObjectAdmin soAdmin = gisServerConnection.ServerObjectAdmin;
                if (!ValidateConfigName(soAdmin, ref configName, host)) return;
                soAdmin.StopConfiguration(configName, "ImageServer");
                if (soAdmin.GetConfigurationStatus(configName, "ImageServer").Status == esriConfigurationStatus.esriCSStopped)
                    Console.WriteLine("{0} on {1} was stopped successfully.", configName, host);
                else
                    Console.WriteLine("{0} on {1} couldn't be stopped, please investigate.", configName, host);
            }
            catch (Exception exc)
            {
                Console.WriteLine("Error: {0}", exc.Message);
            }
        }

        /// <summary>
        /// pause a service
        /// </summary>
        private static void PauseService()
        {
            try
            {
                if (!ConnectAGS(host)) return;
                IServerObjectAdmin soAdmin = gisServerConnection.ServerObjectAdmin;
                if (!ValidateConfigName(soAdmin, ref configName, host)) return;
                if ((soAdmin.GetConfigurationStatus(configName, "ImageServer").Status == esriConfigurationStatus.esriCSStopped))
                {
                    Console.WriteLine("{0} on {1} is currently stopped --- not paused.", configName, host);
                    return;
                }
                soAdmin.PauseConfiguration(configName, "ImageServer");
                if (soAdmin.GetConfigurationStatus(configName, "ImageServer").Status == esriConfigurationStatus.esriCSPaused)
                    Console.WriteLine("{0} on {1} was paused successfully.", configName, host);
                else
                    Console.WriteLine("{0} on {1} couldn't be paused, please investigate.", configName, host);
            }
            catch (Exception exc)
            {
                Console.WriteLine("Error: {0}", exc.Message);
            }
        }

        /// <summary>
        /// List services
        /// </summary>
        private static void ListServices()
        {
            try
            {
                if (!ConnectAGS(host)) return;
                IServerObjectAdmin soAdmin = gisServerConnection.ServerObjectAdmin;
                IEnumServerObjectConfiguration enumConfigs = soAdmin.GetConfigurations();
                enumConfigs.Reset();
                IServerObjectConfiguration soConfig = enumConfigs.Next();
                Console.WriteLine("ArcGIS Server {0} has the following image services:", host);
                while (soConfig != null)
                {
                    if (soConfig.TypeName == "ImageServer")
                        Console.WriteLine("{0}", soConfig.Name);
                    soConfig = enumConfigs.Next();
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine("Error: {0}", exc.Message);
            }
        }
        #endregion


        #region validation etc.
        /// <summary>
        /// connect to ags server
        /// </summary>
        /// <param name="host">host</param>
        /// <returns>true if connected</returns>
        private static bool ConnectAGS(string host)
        {
            try
            {
                gisServerConnection = new GISServerConnectionClass();
                gisServerConnection.Connect(host);
                return true;
            }
            catch (Exception exc)
            {
                Console.WriteLine("Error: Couldn't connect to AGSServer: {0}. Message: {1}", host, exc.Message);
                return false;
            }
        }

        /// <summary>
        /// Validate ConfigName
        /// </summary>
        /// <returns>Convert the config name to the correct case and returns true; if not exist in any cases, returns false </returns>
        private static bool ValidateConfigName(IServerObjectAdmin soAdmin, ref string configName, string host)
        {
            IEnumServerObjectConfiguration enumConfigs = soAdmin.GetConfigurations();
            enumConfigs.Reset();
            IServerObjectConfiguration soConfig = enumConfigs.Next();
            while (soConfig != null)
            {
                if (soConfig.Name.ToUpper() == configName.ToUpper())
                {
                    configName = soConfig.Name;
                    return true;
                }
                soConfig = enumConfigs.Next();
            }
            Console.WriteLine("Configuration {0} on {1} can not be found.", configName, host);
            return false;
        }

        /// <summary>
        /// Validate input parameters
        /// </summary>
        /// <param name="args">args</param>
        /// <returns>validation result</returns>
        private static bool ValidateParams(string[] args)
        {
            //at least two params
            if (args.Length < 2) // at least -o action
            {
                ShowUsage();
                return false;
            }

            // must start with -o
            string[] operations = new string[] { "publish", "delete", "start", "stop", "pause", "list" };
            if ((!args[0].StartsWith("-o")) || (!strInArray(args[1].ToLower(), operations)))
            {
                Console.WriteLine("Incorrect operation");
                ShowUsage();
                return false;
            }

            // for stop/start/pause/list, must contains "-n" and argument length is 4
            if ((args[1].ToLower() == "stop") || (args[1].ToLower() == "start") || (args[1].ToLower() == "pause") || (args[1].ToLower() == "delete"))
            {
                if (!strInArray("-h", args))
                {
                    Console.WriteLine("Missing host server -h");
                    return false;
                }
                if (!strInArray("-n", args))
                {
                    Console.WriteLine("Missing service name switch -n");
                    return false;
                }
                if (args.Length > 6)
                {
                    Console.WriteLine("Too many arguments");
                    return false;
                }
            }
            // for publish, must contains "-d" "-n" and argument length is 6
            if (args[1].ToLower() == "publish")
            {
                if (!strInArray("-d", args))
                {
                    Console.WriteLine("Missing data source switch -d");
                    return false;
                }
                if (!strInArray("-n", args))
                {
                    Console.WriteLine("Missing service name switch -n");
                    return false;
                }
                if (args.Length > 8)
                {
                    Console.WriteLine("Too many arguments");
                    return false;
                }
            }
            // validate each parameter: host, sourcepath, configname
            string[] parameters = new string[] { "-h", "-d", "-n" };
            for (int i = 2; i < args.Length; i++)
            {
                switch (args[i])
                {
                    case "-h":
                        if (i == args.Length - 1)
                        {
                            Console.WriteLine("Missing host parameter, switch -h");
                            return false;
                        }
                        else if (strInArray(args[i + 1], parameters))
                        {
                            Console.WriteLine("Missing host parameter, switch -h");
                            return false;
                        }
                        ++i;
                        break;
                    case "-d":
                        if (i == args.Length - 1)
                        {
                            Console.WriteLine("Missing data source parameter, switch -d");
                            return false;
                        }
                        else if (strInArray(args[i + 1], parameters))
                        {
                            Console.WriteLine("Missing data source parameter, switch -d");
                            return false;
                        }
                        ++i;
                        break;
                    case "-n":
                        if (i == args.Length - 1)
                        {
                            Console.WriteLine("Missing service name parameter, switch -n");
                            return false;
                        }
                        else if (strInArray(args[i + 1], parameters))
                        {
                            Console.WriteLine("Missing service name parameter, switch -n");
                            return false;
                        }
                        ++i;
                        break;
                    default:
                        Console.WriteLine("Incorrect parameter switch: {0} is not a recognized.", args[i]);
                        return false;
                }
            }
            return true;
        }

        /// <summary>
        /// string in array
        /// </summary>
        /// <param name="name"></param>
        /// <param name="nameArray"></param>
        /// <returns></returns>
        private static bool strInArray(string name, string[] nameArray)
        {
            for (int i = 0; i < nameArray.Length; i++)
            {
                if (nameArray[i] == name)
                    return true;
            }
            return false;
        }

        /// <summary>
        /// initialize license
        /// </summary>
        /// <returns>status</returns>
        private static bool InitLicense()
        {
            RuntimeManager.Bind(ProductCode.Desktop);
            IAoInitialize aoInit = new AoInitializeClass();
            string license = System.Environment.GetEnvironmentVariable("ARCLICENSE");
            esriLicenseStatus status = aoInit.Initialize(esriLicenseProductCode.esriLicenseProductCodeArcView);
            if (status != esriLicenseStatus.esriLicenseCheckedOut)
            {
                Console.WriteLine("License initialization  error");
                return false;
            }
            else
                return true;
        }
        #endregion


        #region helper methods
        /// <summary>
        /// Retrieve parameters
        /// </summary>
        /// <param name="args">args</param>
        private static void Retrieve_Params(string[] args)
        {
            for (int i = 2; i < args.Length; i++)
            {
                switch (args[i])
                {
                    case "-h":
                        host = args[++i];
                        break;
                    case "-d":
                        sourcePath = args[++i];
                        break;
                    case "-n":
                        configName = args[++i];
                        break;
                }
            }
        }

        /// <summary>
        /// Get Source Type
        /// </summary>
        /// <param name="sourcePath">path of the data source</param>
        /// <returns>data source type</returns>
        private static esriImageServiceSourceType GetSourceType(string sourcePath)
        {
            if (sourcePath.ToLower().EndsWith(".iscdef"))
                return esriImageServiceSourceType.esriImageServiceSourceTypeCatalog;
            else if (sourcePath.ToLower().EndsWith(".lyr"))
                return esriImageServiceSourceType.esriImageServiceSourceTypeLayer;
            else
            {
                FileInfo fileInfo = new FileInfo(sourcePath);
                OpenRasterDataset(fileInfo.DirectoryName, fileInfo.Name);
                if (rasterDataset is IMosaicDataset)
                    return esriImageServiceSourceType.esriImageServiceSourceTypeMosaicDataset;
                else
                    return esriImageServiceSourceType.esriImageServiceSourceTypeDataset;
            }
        }

        /// <summary>
        /// Open Raster Dataset
        /// </summary>
        /// <param name="path">path of the dataset</param>
        /// <param name="rasterDSName">name of the dataset</param>        
        private static void OpenRasterDataset(String path, String rasterDSName)
        {
            //this is why the utility user needs access to data source. image service configurations varies among data sources.
            IWorkspaceFactory workspaceFactory = null;
            IWorkspace workspace = null;
            IRasterWorkspaceEx rasterWorkspaceEx = null;
            Type factoryType = null;
            try
            {
                switch (path.Substring(path.Length - 4, 4).ToLower()) // a path can never be shorter than 4 characters, isn't it? c:\a
                {
                    case ".mdb":
                        factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.AccessWorkspaceFactory");
                        workspaceFactory = Activator.CreateInstance(factoryType) as IWorkspaceFactory;
                        workspace = workspaceFactory.OpenFromFile(path, 1);
                        rasterWorkspaceEx = (IRasterWorkspaceEx)workspace;
                        rasterDataset = rasterWorkspaceEx.OpenRasterDataset(rasterDSName);
                        break;
                    case ".gdb":
                        factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
                        workspaceFactory = Activator.CreateInstance(factoryType) as IWorkspaceFactory;
                        workspace = workspaceFactory.OpenFromFile(path, 1);
                        rasterWorkspaceEx = (IRasterWorkspaceEx)workspace;
                        rasterDataset = rasterWorkspaceEx.OpenRasterDataset(rasterDSName);
                        break;
                    case ".sde":
                        factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.SdeWorkspaceFactory");
                        workspaceFactory = Activator.CreateInstance(factoryType) as IWorkspaceFactory;
                        workspace = workspaceFactory.OpenFromFile(path, 1);
                        rasterWorkspaceEx = (IRasterWorkspaceEx)workspace;
                        rasterDataset = rasterWorkspaceEx.OpenRasterDataset(rasterDSName);
                        break;
                    default:
                        factoryType = Type.GetTypeFromProgID("esriDataSourcesRaster.RasterWorkspaceFactory");
                        workspaceFactory = Activator.CreateInstance(factoryType) as IWorkspaceFactory;
                        workspace = workspaceFactory.OpenFromFile(path, 1);
                        IRasterWorkspace rasterWorkspace = (IRasterWorkspace)workspace;
                        rasterDataset = rasterWorkspace.OpenRasterDataset(rasterDSName);
                        break;
                }
            }
            catch (Exception)
            {
                throw new ArgumentException("Failed to open source data");
            }
        }

        /// <summary>
        /// Show usage
        /// </summary>
        private static void ShowUsage()
        {
            Console.WriteLine();
            Console.WriteLine("ArcObject Sample: command line image service configuration utility.");
            Console.WriteLine();
            Console.WriteLine("Usage. <>: required parameter; |: pick one.");
            Console.WriteLine("isconfig -o publish -h <host> -d <datapath> -n <configName>");
            Console.WriteLine("isconfig -o <delete|start|stop|pause> -h <host> -n <configName>");
            Console.WriteLine("isconfig -o <list> -h <host>");
        }
        #endregion

    }
}

[Visual Basic .NET]

ISConfig.vb

Imports System.IO
Imports ESRI.ArcGIS
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.Server
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.DataSourcesGDB
Imports ESRI.ArcGIS.DataSourcesRaster
' 1. Description:
' This sample demonstrate how to create an image service and set configurations based on data source types (raster dataset, mosaic dataset, compiled image service definition, raster layer); it also have additional features to start,stop,delete image service programmatically.
' The user running this utility needs to be in the agsadmin group on ArcGIS Server; and needs access to data source
' The application can be run locally on AGSServer machine (localhost), or remotely. If source data is iscdef, image server must be already registered on ArcGIS Server.
' 2. Case sensitivity:  
' (1) switches are case sensitive. 
' (2) when publish a service, the service name is case sensitive
' e.g. If it's published to a folder, e.g. Temporary/Test1. "Temporary" must match the case.
' 3. Usage:
' Run from command line environment. Usage. <>: required parameter; |: pick one.
' isconfig -o publish -h <host> -d <datapath> -n <configName>
' isconfig -o <delete|start|stop|pause> -h <host> -n <configName>
' isconfig -o <list> -h <host>
' Example 1: isconfig -o publish -h localhost -d \\myserver\data\test.gdb\mdtest -n mdtest
' Example 2: isconfig -o stop -h myservername -n mdtest
' Example 3: isconfig -o list -h myservername
Class ISConfig
	#Region "static variables"
	Private Shared sourcePath As String = ""
	'data source path: a raster dataset, an iscdef, a mosaic dataset
	Private Shared host As String = ""
	'host machine; use "localhost" for local ags server
	Private Shared configName As String = ""
	'image service configuration name
	Private Shared gisServerConnection As IGISServerConnection2 = Nothing
	Private Shared rasterDataset As IRasterDataset = Nothing

	#End Region

    <STAThread()> _
    Public Shared Sub Main(ByVal args As String())

        Try
            'validation
            If Not ValidateParams(args) Then
                Return
            End If
            'license           
            If Not InitLicense() Then
                Return
            End If
            'retrieve parameters
            Retrieve_Params(args)
            Dim operation As String = args(1)
            Select Case operation.ToLower()
                Case "publish"
                    CreateISConfig()
                    Exit Select
                Case "delete"
                    DeleteService()
                    Exit Select
                Case "start"
                    StartService()
                    Exit Select
                Case "stop"
                    StopService()
                    Exit Select
                Case "pause"
                    PauseService()
                    Exit Select
                Case "list"
                    ListServices()
                    Exit Select
            End Select
        Catch exc As Exception
            Console.WriteLine("Error: {0}", exc.Message)
        End Try
    End Sub


	#Region "management operations"
	''' <summary>
	''' create image service configuration
	''' </summary>
	Private Shared Sub CreateISConfig()
		Try
			If Not ConnectAGS(host) Then
				Return
			End If
			Dim sourceType As esriImageServiceSourceType = GetSourceType(sourcePath)
			'connect to ArcGIS Server and create configuration
			Dim gisServerConnection As IGISServerConnection = New GISServerConnectionClass()
			gisServerConnection.Connect(host)
			Dim soAdmin As IServerObjectAdmin = gisServerConnection.ServerObjectAdmin
			Dim soConfig As IServerObjectConfiguration = DirectCast(soAdmin.CreateConfiguration(), IServerObjectConfiguration)

			'set general service parameters
			soConfig.Name = configName
			soConfig.TypeName = "ImageServer"
			soConfig.StartupType = esriStartupType.esriSTAutomatic
			soConfig.IsPooled = True
			soConfig.IsolationLevel = esriServerIsolationLevel.esriServerIsolationHigh
			soConfig.MinInstances = 1
			soConfig.MaxInstances = 2
			Dim propertySet_Recycle As IPropertySet = soConfig.RecycleProperties
            propertySet_Recycle.SetProperty("Start", "00:00")
            propertySet_Recycle.SetProperty("Interval", "86400")
			Dim propertySet As IPropertySet = soConfig.Properties
			If sourceType = esriImageServiceSourceType.esriImageServiceSourceTypeCatalog Then
				'(sourceDataPath.ToLower().EndsWith(".iscdef"))
				propertySet.SetProperty("ServiceDefinition", sourcePath)
			Else
				propertySet.SetProperty("Path", sourcePath)
			End If
            propertySet.SetProperty("SupportedImageReturnTypes", "URL")
			'virtual directory
			Dim dirs As IEnumServerDirectory = soAdmin.GetServerDirectories()
			dirs.Reset()
			Dim serverDir As IServerDirectory = dirs.[Next]()
			While serverDir IsNot Nothing
				If DirectCast(serverDir, IServerDirectory2).Type = esriServerDirectoryType.esriSDTypeOutput Then
					propertySet.SetProperty("OutputDir", serverDir.Path)
					propertySet.SetProperty("VirtualOutputDir", serverDir.URL)
					Exit While
				End If
				serverDir = dirs.[Next]()
            End While


			'properties for a mosaic dataset;
			If sourceType = esriImageServiceSourceType.esriImageServiceSourceTypeMosaicDataset Then
				Dim functionRasterDataset As IFunctionRasterDataset = DirectCast(rasterDataset, IFunctionRasterDataset)
				Dim propDefaults As IPropertySet = functionRasterDataset.Properties
				propertySet.SetProperty("MaxImageHeight", propDefaults.GetProperty("MaxImageHeight"))
				'4100
				propertySet.SetProperty("MaxImageWidth", propDefaults.GetProperty("MaxImageWidth"))
				'15000
				propertySet.SetProperty("AllowedCompressions", propDefaults.GetProperty("AllowedCompressions"))
				'"None,JPEG,LZ77"
				propertySet.SetProperty("DefaultResamplingMethod", propDefaults.GetProperty("DefaultResamplingMethod"))
				'0
				propertySet.SetProperty("DefaultCompressionQuality", propDefaults.GetProperty("DefaultCompressionQuality"))
				'75
				propertySet.SetProperty("MaxRecordCount", propDefaults.GetProperty("MaxRecordCount"))
				'500
				propertySet.SetProperty("MaxMosaicImageCount", propDefaults.GetProperty("MaxMosaicImageCount"))
				'20
				propertySet.SetProperty("MaxDownloadImageCount", propDefaults.GetProperty("MaxDownloadImageCount"))
				'20
				propertySet.SetProperty("AllowedFields", propDefaults.GetProperty("AllowedFields"))
				'"Name,MinPS,MaxPS,LowPS,HighPS,CenterX,CenterY"
				propertySet.SetProperty("AllowedMosaicMethods", propDefaults.GetProperty("AllowedMosaicMethods"))
				'"Center,NorthWest,LockRaster,ByAttribute,Nadir,Viewpoint,Seamline"
				propertySet.SetProperty("AllowedItemMetadata", propDefaults.GetProperty("AllowedItemMetadata"))
				'"Full"
                'propertySet.SetProperty("DownloadDir", "") 'put download dir here
                'propertySet.SetProperty("VirutalDownloadDir", "") 'put virtual download dir here
			ElseIf sourceType <> esriImageServiceSourceType.esriImageServiceSourceTypeCatalog Then
				'not iscdef
				propertySet.SetProperty("MaxImageHeight", 4100)
				propertySet.SetProperty("MaxImageWidth", 15000)
				propertySet.SetProperty("AllowedCompressions", "None,JPEG,LZ77")
				propertySet.SetProperty("DefaultResamplingMethod", 0)
				propertySet.SetProperty("DefaultCompressionQuality", 75)
			End If

			'enable web capabilities
			Dim soConfig2 As IServerObjectConfiguration2 = DirectCast(soConfig, IServerObjectConfiguration2)
			soConfig2.Info.SetProperty("WebEnabled", "true")
			If sourceType = esriImageServiceSourceType.esriImageServiceSourceTypeMosaicDataset Then
				soConfig2.Info.SetProperty("WebCapabilities", "Image,Catalog,Metadata,Download,Pixels")
			Else
                soConfig2.Info.SetProperty("WebCapabilities", "Image,Metadata")
			End If

            'enable wcs, assume data has spatial reference
            soConfig2.ExtensionEnabled("WCSServer") = True
            Dim propertySetWCS As IPropertySet = soConfig2.ExtensionInfo("WCSServer")
            propertySetWCS.SetProperty("WebEnabled", True)

            'enable wms
            soConfig2.ExtensionEnabled("WMSServer") = True
            Dim propertySetWMS As IPropertySet = soConfig2.ExtensionInfo("WMSServer")
            propertySetWMS.SetProperty("WebEnabled", "true")

            'add configuration and start
            soAdmin.AddConfiguration(soConfig)
            soAdmin.StartConfiguration(configName, "ImageServer")

            If soAdmin.GetConfigurationStatus(configName, "ImageServer").Status = esriConfigurationStatus.esriCSStarted Then
                Console.WriteLine("{0} on {1} has been configured and started.", configName, host)
            Else
                Console.WriteLine("{0} on {1} was configured but can not be started, please investigate.", configName, host)
            End If
        Catch exc As Exception
            Console.WriteLine("Error: {0}", exc.Message)
        End Try
	End Sub

	''' <summary>
	''' delete a service
	''' </summary>
	Private Shared Sub DeleteService()
		Try
			If Not ConnectAGS(host) Then
				Return
			End If
			Dim soAdmin As IServerObjectAdmin = gisServerConnection.ServerObjectAdmin
			If Not ValidateConfigName(soAdmin, configName, host) Then
				Return
			End If
			soAdmin.DeleteConfiguration(configName, "ImageServer")
			Console.WriteLine("{0} on {1} was deleted successfully.", configName, host)
		Catch exc As Exception
			Console.WriteLine("Error: {0}", exc.Message)
		End Try
	End Sub

	''' <summary>
	''' start a service
	''' </summary>
	Private Shared Sub StartService()
		Try
			If Not ConnectAGS(host) Then
				Return
			End If
			Dim soAdmin As IServerObjectAdmin = gisServerConnection.ServerObjectAdmin
			If Not ValidateConfigName(soAdmin, configName, host) Then
				Return
			End If
			soAdmin.StartConfiguration(configName, "ImageServer")
			If soAdmin.GetConfigurationStatus(configName, "ImageServer").Status = esriConfigurationStatus.esriCSStarted Then
				Console.WriteLine("{0} on {1} was started successfully.", configName, host)
			Else
				Console.WriteLine("{0} on {1} couldn't be started, please investigate.", configName, host)
			End If
		Catch exc As Exception
			Console.WriteLine("Error: {0}", exc.Message)
		End Try
	End Sub

	''' <summary>
	''' stop a service
	''' </summary>
	Private Shared Sub StopService()
		Try
			If Not ConnectAGS(host) Then
				Return
			End If
			Dim soAdmin As IServerObjectAdmin = gisServerConnection.ServerObjectAdmin
			If Not ValidateConfigName(soAdmin, configName, host) Then
				Return
			End If
			soAdmin.StopConfiguration(configName, "ImageServer")
			If soAdmin.GetConfigurationStatus(configName, "ImageServer").Status = esriConfigurationStatus.esriCSStopped Then
				Console.WriteLine("{0} on {1} was stopped successfully.", configName, host)
			Else
				Console.WriteLine("{0} on {1} couldn't be stopped, please investigate.", configName, host)
			End If
		Catch exc As Exception
			Console.WriteLine("Error: {0}", exc.Message)
		End Try
	End Sub

	''' <summary>
	''' pause a service
	''' </summary>
	Private Shared Sub PauseService()
		Try
			If Not ConnectAGS(host) Then
				Return
			End If
			Dim soAdmin As IServerObjectAdmin = gisServerConnection.ServerObjectAdmin
			If Not ValidateConfigName(soAdmin, configName, host) Then
				Return
			End If
			If (soAdmin.GetConfigurationStatus(configName, "ImageServer").Status = esriConfigurationStatus.esriCSStopped) Then
				Console.WriteLine("{0} on {1} is currently stopped --- not paused.", configName, host)
				Return
			End If
			soAdmin.PauseConfiguration(configName, "ImageServer")
			If soAdmin.GetConfigurationStatus(configName, "ImageServer").Status = esriConfigurationStatus.esriCSPaused Then
				Console.WriteLine("{0} on {1} was paused successfully.", configName, host)
			Else
				Console.WriteLine("{0} on {1} couldn't be paused, please investigate.", configName, host)
			End If
		Catch exc As Exception
			Console.WriteLine("Error: {0}", exc.Message)
		End Try
	End Sub


	Private Shared Sub ListServices()
		Try
			If Not ConnectAGS(host) Then
				Return
			End If
			Dim soAdmin As IServerObjectAdmin = gisServerConnection.ServerObjectAdmin
			Dim enumConfigs As IEnumServerObjectConfiguration = soAdmin.GetConfigurations()
			enumConfigs.Reset()
			Dim soConfig As IServerObjectConfiguration = enumConfigs.[Next]()
			Console.WriteLine("ArcGIS Server {0} has the following image services:", host)
			While soConfig IsNot Nothing
				If soConfig.TypeName = "ImageServer" Then
					Console.WriteLine("{0}", soConfig.Name)
				End If
				soConfig = enumConfigs.[Next]()
			End While
		Catch exc As Exception
			Console.WriteLine("Error: {0}", exc.Message)
		End Try
	End Sub
	#End Region


	#Region "validation etc."
	''' <summary>
	''' connect to ags server
	''' </summary>
	''' <param name="host">host</param>
	''' <returns>true if connected</returns>
	Private Shared Function ConnectAGS(host As String) As Boolean
		Try
			gisServerConnection = New GISServerConnectionClass()
			gisServerConnection.Connect(host)
			Return True
		Catch exc As Exception
			Console.WriteLine("Error: Couldn't connect to AGSServer: {0}. Message: {1}", host, exc.Message)
			Return False
		End Try
	End Function

	''' <summary>
	''' Validate ConfigName
	''' </summary>
	''' <returns>Convert the config name to the correct case and returns true; if not exist in any cases, returns false </returns>
	Private Shared Function ValidateConfigName(soAdmin As IServerObjectAdmin, ByRef configName As String, host As String) As Boolean
		Dim enumConfigs As IEnumServerObjectConfiguration = soAdmin.GetConfigurations()
		enumConfigs.Reset()
		Dim soConfig As IServerObjectConfiguration = enumConfigs.[Next]()
		While soConfig IsNot Nothing
			If soConfig.Name.ToUpper() = configName.ToUpper() Then
				configName = soConfig.Name
				Return True
			End If
			soConfig = enumConfigs.[Next]()
		End While
		Console.WriteLine("Configuration {0} on {1} can not be found.", configName, host)
		Return False
	End Function

	''' <summary>
	''' Validate input parameters
	''' </summary>
	''' <param name="args">args</param>
	''' <returns>validation result</returns>
	Private Shared Function ValidateParams(args As String()) As Boolean
		'at least two params
		If args.Length < 2 Then
			' at least -o action
			ShowUsage()
			Return False
		End If

		' must start with -o
		Dim operations As String() = New String() {"publish", "delete", "start", "stop", "pause", "list"}
		If (Not args(0).StartsWith("-o")) OrElse (Not strInArray(args(1).ToLower(), operations)) Then
			Console.WriteLine("Incorrect operation")
			ShowUsage()
			Return False
		End If

		' for stop/start/pause/list, must contains "-n" and argument length is 4
		If (args(1).ToLower() = "stop") OrElse (args(1).ToLower() = "start") OrElse (args(1).ToLower() = "pause") OrElse (args(1).ToLower() = "delete") Then
			If Not strInArray("-h", args) Then
				Console.WriteLine("Missing host server -h")
				Return False
			End If
			If Not strInArray("-n", args) Then
				Console.WriteLine("Missing service name switch -n")
				Return False
			End If
			If args.Length > 6 Then
				Console.WriteLine("Too many arguments")
				Return False
			End If
		End If
		' for publish, must contains "-d" "-n" and argument length is 6
		If args(1).ToLower() = "publish" Then
			If Not strInArray("-d", args) Then
				Console.WriteLine("Missing data source switch -d")
				Return False
			End If
			If Not strInArray("-n", args) Then
				Console.WriteLine("Missing service name switch -n")
				Return False
			End If
			If args.Length > 8 Then
				Console.WriteLine("Too many arguments")
				Return False
			End If
		End If
		' validate each parameter: host, sourcepath, configname
		Dim parameters As String() = New String() {"-h", "-d", "-n"}
		For i As Integer = 2 To args.Length - 1
			Select Case args(i)
				Case "-h"
					If i = args.Length - 1 Then
						Console.WriteLine("Missing host parameter, switch -h")
						Return False
					ElseIf strInArray(args(i + 1), parameters) Then
						Console.WriteLine("Missing host parameter, switch -h")
						Return False
					End If
					i += 1
					Exit Select
				Case "-d"
					If i = args.Length - 1 Then
						Console.WriteLine("Missing data source parameter, switch -d")
						Return False
					ElseIf strInArray(args(i + 1), parameters) Then
						Console.WriteLine("Missing data source parameter, switch -d")
						Return False
					End If
					i += 1
					Exit Select
				Case "-n"
					If i = args.Length - 1 Then
						Console.WriteLine("Missing service name parameter, switch -n")
						Return False
					ElseIf strInArray(args(i + 1), parameters) Then
						Console.WriteLine("Missing service name parameter, switch -n")
						Return False
					End If
					i += 1
					Exit Select
				Case Else
					Console.WriteLine("Incorrect parameter switch: {0} is not a recognized.", args(i))
					Return False
			End Select
		Next
		Return True
	End Function

	''' <summary>
	''' string in array
	''' </summary>
	''' <param name="name"></param>
	''' <param name="nameArray"></param>
	''' <returns></returns>
	Private Shared Function strInArray(name As String, nameArray As String()) As Boolean
		For i As Integer = 0 To nameArray.Length - 1
			If nameArray(i) = name Then
				Return True
			End If
		Next
		Return False
	End Function

	''' <summary>
	''' initialize license
	''' </summary>
	''' <returns>status</returns>
	Private Shared Function InitLicense() As Boolean
		RuntimeManager.Bind(ProductCode.Desktop)
		Dim aoInit As IAoInitialize = New AoInitializeClass()
		Dim license As String = System.Environment.GetEnvironmentVariable("ARCLICENSE")
        Dim status As esriLicenseStatus = aoInit.Initialize(esriLicenseProductCode.esriLicenseProductCodeArcView)
		If status <> esriLicenseStatus.esriLicenseCheckedOut Then
			Console.WriteLine("License initialization  error")
			Return False
		Else
			Return True
		End If
	End Function
	#End Region


#Region "helper methods"
    ''' <summary>
    ''' Retrieve parameters
    ''' </summary>
    ''' <param name="args">args</param>
    Private Shared Sub Retrieve_Params(ByVal args As String())
        For i As Integer = 2 To args.Length - 1
            Select Case args(i)
                Case "-h"
                    host = args(System.Threading.Interlocked.Increment(i))
                    Exit Select
                Case "-d"
                    sourcePath = args(System.Threading.Interlocked.Increment(i))
                    Exit Select
                Case "-n"
                    configName = args(System.Threading.Interlocked.Increment(i))
                    Exit Select
            End Select
        Next
    End Sub

    ''' <summary>
    ''' Get Source Type
    ''' </summary>
    ''' <param name="sourcePath">path of the data source</param>
    ''' <returns>data source type</returns>
    Private Shared Function GetSourceType(ByVal sourcePath As String) As esriImageServiceSourceType
        If sourcePath.ToLower().EndsWith(".iscdef") Then
            Return esriImageServiceSourceType.esriImageServiceSourceTypeCatalog
        ElseIf sourcePath.ToLower().EndsWith(".lyr") Then
            Return esriImageServiceSourceType.esriImageServiceSourceTypeLayer
        Else
            Dim fileInfo As FileInfo = New FileInfo(sourcePath)
            OpenRasterDataset(fileInfo.DirectoryName, fileInfo.Name)
            If TypeOf rasterDataset Is IMosaicDataset Then
                Return esriImageServiceSourceType.esriImageServiceSourceTypeMosaicDataset
            Else
                Return esriImageServiceSourceType.esriImageServiceSourceTypeDataset
            End If
        End If
    End Function

    ''' <summary>
    ''' Open Raster Dataset
    ''' </summary>
    ''' <param name="path">path of the dataset</param>
    ''' <param name="rasterDSName">name of the dataset</param>
    ''' <returns>a raster dataset object</returns>
    Private Shared Sub OpenRasterDataset(ByVal path As String, ByVal rasterDSName As String)
        'this is why the utility user needs access to data source. image service configurations varies among data sources.
        Dim workspaceFactory As IWorkspaceFactory = Nothing
        Dim workspace As IWorkspace = Nothing
        Dim rasterWorkspaceEx As IRasterWorkspaceEx = Nothing
        Dim factoryType As Type = Nothing
        Try
            Select Case path.Substring(path.Length - 4, 4).ToLower()
                ' a path can never be shorter than 4 characters, isn't it? c:\a
                Case ".mdb"
                    factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.AccessWorkspaceFactory")
                    workspaceFactory = CType(Activator.CreateInstance(factoryType), IWorkspaceFactory)
                    workspace = workspaceFactory.OpenFromFile(path, 1)
                    rasterWorkspaceEx = CType(workspace, IRasterWorkspaceEx)
                    rasterDataset = rasterWorkspaceEx.OpenRasterDataset(rasterDSName)
                    Exit Select
                Case ".gdb"
                    factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory")
                    workspaceFactory = CType(Activator.CreateInstance(factoryType), IWorkspaceFactory)
                    workspace = workspaceFactory.OpenFromFile(path, 1)
                    rasterWorkspaceEx = CType(workspace, IRasterWorkspaceEx)
                    rasterDataset = rasterWorkspaceEx.OpenRasterDataset(rasterDSName)
                    Exit Select
                Case ".sde"
                    factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.SdeWorkspaceFactory")
                    workspaceFactory = CType(Activator.CreateInstance(factoryType), IWorkspaceFactory)
                    workspace = workspaceFactory.OpenFromFile(path, 1)
                    rasterWorkspaceEx = CType(workspace, IRasterWorkspaceEx)
                    rasterDataset = rasterWorkspaceEx.OpenRasterDataset(rasterDSName)
                    Exit Select
                Case Else
                    factoryType = Type.GetTypeFromProgID("esriDataSourcesRaster.RasterWorkspaceFactory")
                    workspaceFactory = CType(Activator.CreateInstance(factoryType), IWorkspaceFactory)
                    workspace = workspaceFactory.OpenFromFile(path, 1)
                    Dim rasterWS As IRasterWorkspace = CType(workspace, IRasterWorkspace)
                    rasterDataset = rasterWS.OpenRasterDataset(rasterDSName)
                    Exit Select
            End Select
        Catch generatedExceptionName As Exception
            Throw New ArgumentException("Failed to open source data")
        End Try
    End Sub

    ''' <summary>
    ''' Show usage
    ''' </summary>
    Private Shared Sub ShowUsage()
        Console.WriteLine()
        Console.WriteLine("ArcObject Sample: command line image service configuration utility.")
        Console.WriteLine()
        Console.WriteLine("Usage. <>: required parameter; |: pick one.")
        Console.WriteLine("isconfig -o publish -h <host> -d <datapath> -n <configName>")
        Console.WriteLine("isconfig -o <delete|start|stop|pause> -h <host> -n <configName>")
        Console.WriteLine("isconfig -o <list> -h <host>")
    End Sub
#End Region

End Class