I am working with a Powerpoint slide and try to extract the names of all shapes with charts from the slide. I can find out if the Slide has charts at all, but I am stuck as to how to find the correspondending Slide.
code:
// suppose that a presentation is correctly loaded
private List<PPChart> GetChartsfromSlide(SlidePart slidepart)
{
var chartList = new List<PPChart>();
if (slidepart.ChartParts.Any())
{
foreach (var chart in slidepart.ChartParts)
{
// how to get the ID of the Chart and get the corespondending slide?
}
}
return chartList;
}
I found a solution, but the Solution is rather involved:
Hopefully, it helps somebody in the future...
/// <summary>
/// Gets a List of all Charts on this Slide
/// </summary>
/// <param name="slidepart">The SlidePart.</param>
/// <returns>A List of all Charts on this Slide</returns>
private List<PPChart> GetChartsfromSlide(SlidePart slidepart)
{
var chartList = new List<PPChart>();
if (slidepart.ChartParts.Any())
{
foreach (var chart in slidepart.ChartParts)
{
//// get the ID of the Chart-Part
var id = slidepart.GetIdOfPart(chart);
//// Get a list of all Shapes(Graphicframes) which contain Charts
var gshapes = from shapeDesc in slidepart.Slide.Descendants<GraphicFrame>() select shapeDesc;
var tempgshapes = gshapes.ToList();
//// Select all possible Shapes which have Graphics
var thisShape = from Gshape in tempgshapes where this.HasThisChart(id, Gshape) select Gshape;
var result = thisShape.ToList();
this.logger.Debug("Found Chart with ID:{0} Name:{1}", result[0].NonVisualGraphicFrameProperties.NonVisualDrawingProperties.Id, result[0].NonVisualGraphicFrameProperties.NonVisualDrawingProperties.Name);
var ppchart = new PPChart(result[0].NonVisualGraphicFrameProperties.NonVisualDrawingProperties.Id);
ppchart.ShapeName = result[0].NonVisualGraphicFrameProperties.NonVisualDrawingProperties.Name;
chartList.Add(ppchart);
}
}
return chartList;
}
/// <summary>
/// Determines whether the Slider has this Chart or not.
/// </summary>
/// <param name="id">The id.</param>
/// <param name="gframe">The gframe.</param>
/// <returns>
/// <c>true</c> if the Slide has the chart; otherwise, <c>false</c>.
/// </returns>
private bool HasThisChart(string id, GraphicFrame gframe)
{
var returnValue = false;
if (!(gframe == null) && this.HasGraphic(gframe))
{
if (!(gframe.Graphic.GraphicData == null))
{
var graphicData = gframe.Graphic.GraphicData;
var drawChartsRef = graphicData.Descendants<DrawCharts.ChartReference>();
if (!(drawChartsRef == null))
{
foreach (var drawChart in drawChartsRef)
{
if (drawChart.Id == id)
{
returnValue = true;
}
}
}
}
}
return returnValue;
}
/// <summary>
/// Determines whether the specified GraphicFrame has a graphic (A graphic is a chart!).
/// </summary>
/// <param name="gframe">The gframe.</param>
/// <returns>
/// <c>true</c> if the specified gframe has a graphic; otherwise, <c>false</c>.
/// </returns>
private bool HasGraphic(GraphicFrame gframe)
{
var returnValue = false;
if (!(gframe == null))
{
var graphicDescendants = gframe.Descendants<Draw.Graphic>();
if (graphicDescendants.Count() > 0)
{
returnValue = true;
}
}
return returnValue;
}
Related
Can anyone help me with the implementation of WMTS / TMS Server in SharpMap?
I've been trying out a lot from diff sources but I can't seem to come up with a working solution. Below is a handler I am using, it's just drawing the boxes instead of data from the database. I am using the same method I used for a WMS Server:
DatabaseUtil.SqlServer(ConnectionString(), Layers(), new Size(1, 1), bbox, "id");
to get data from SQL Server and it's working just fine for the WMS. The only difference is that the one below returns a specific layer instead of a list by using .FindAll(lyr => lyr.Table.Equals(layer)) query.
/// <summary>
/// Summary description for WMTS
/// </summary>
public class WMTS : IHttpHandler
{
/// <summary>
/// Defines the projection
/// </summary>
private readonly ICoordinateTransformation projection = ProjUtil.ToPseudoMercator();
/// <summary>
/// The ProcessRequest
/// wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=layer_id&STYLE=default&TILEMATRIXSET=matrix_id&TILEMATRIX=3&TILEROW=2&TILECOL=0&FORMAT=image%2Fjpeg
/// </summary>
/// <param name="context">The <see cref="HttpContext"/></param>
public void ProcessRequest(HttpContext context)
{
string layer = context.Request.Params["LAYER"];
int tilematrix = int.Parse(context.Request.Params["TILEMATRIX"]);
int tilerow = int.Parse(context.Request.Params["TILEROW"]);
int tilecol = int.Parse(context.Request.Params["TILECOL"]);
string service = context.Request.Params["SERVICE"];
string request = context.Request.Params["REQUEST"];
string version = context.Request.Params["VERSION"];
string style = context.Request.Params["STYLE"];
string tilematrixset = context.Request.Params["TILEMATRIXSET"];
string format = context.Request.Params["FORMAT"];
if (String.IsNullOrEmpty(layer))
throw new ArgumentNullException("layer");
Map map = Map(layer, tilecol, tilerow, tilematrix);
var map_image = map.GetMap();
//using (var memory_stream = new MemoryStream())
//{
// map_image.Save(memory_stream, ImageFormat.Png);
// var wms = memory_stream.ToArray();
// WriteResponseInChunks(wms, context);
//}
byte[] buffer;
using (var ms = new MemoryStream())
{
map_image.Save(ms, ImageFormat.Png);
map_image.Dispose();
buffer = ms.ToArray();
}
WriteResponseInChunks(buffer, context);
}
public static ImageCodecInfo GetEncoderInfo(String mimeType)
{
foreach (var encoder in ImageCodecInfo.GetImageEncoders())
if (encoder.MimeType == mimeType)
return encoder;
return null;
}
/// <summary>
/// The GetMap
/// </summary>
/// <returns>The <see cref="SharpMap.Map"/></returns>
protected Map Map(string layer, int x, int y, int z)
{
Envelope bbox = GetBoundingBoxInLatLngWithMargin(x, y, z);
return DatabaseUtil.SqlServer(ConnectionString(), Layers().FindAll(lyr => lyr.Table.Equals(layer)), new Size(1, 1), bbox, "id");
}
/// <summary>
/// The Layers
/// </summary>
/// <returns>The <see cref="List{VectorLayerModel}"/></returns>
private List<VectorLayerModel> Layers()
{
VectorLayerModel standsLayerModel = new VectorLayerModel()
{
Table = "cadastre",
Style = new VectorStyle { Line = new Pen(Color.DarkGray, 2) }
};
VectorLayerModel roadsLayerModel = new VectorLayerModel()
{
Table = "townships",
Style = new VectorStyle { Line = new Pen(Color.DarkRed, 2.5f) }
};
VectorLayerModel pipeLayerModel = new VectorLayerModel()
{
Table = "provinces",
Style = new VectorStyle { Line = new Pen(Color.DarkBlue, 1.5f) }
};
return new List<VectorLayerModel>() { standsLayerModel, roadsLayerModel, pipeLayerModel };
}
/// <summary>
/// The ConnectionString
/// </summary>
/// <returns>The <see cref="string"/></returns>
private string ConnectionString()
{
return "Data Source=******;Initial Catalog=GCCIGO_V2;Integrated Security=SSPI;";
}
/// <summary>
/// The GetBoundingBoxInLatLngWithMargin
/// </summary>
/// <param name="tileX">The <see cref="int"/></param>
/// <param name="tileY">The <see cref="int"/></param>
/// <param name="zoom">The <see cref="int"/></param>
/// <returns>The <see cref="Envelope"/></returns>
private Envelope GetBoundingBoxInLatLngWithMargin(int tileX, int tileY, int zoom)
{
Point px1 = new Point((tileX * 256), (tileY * 256));
Point px2 = new Point(((tileX + 1) * 256), ((tileY + 1) * 256));
PointF ll1 = TileSystemHelper.PixelXYToLatLong(px1, zoom);
PointF ll2 = TileSystemHelper.PixelXYToLatLong(px2, zoom);
double[] prj1 = projection.MathTransform.Transform(new double[] { ll1.X, ll1.Y });
double[] prj2 = projection.MathTransform.Transform(new double[] { ll2.X, ll2.Y });
Envelope bbox = new Envelope();
bbox.ExpandToInclude(prj1[0], prj1[1]);
bbox.ExpandToInclude(prj2[0], prj2[1]);
return bbox;
}
/// <summary>
/// The size of the chunks written to response.
/// </summary>
private const int ChunkSize = 2 * 8192;
/// <summary>
/// Method to write an array of bytes in chunks to a http response
/// </summary>
/// <remarks>
/// The code was adopted from http://support.microsoft.com/kb/812406/en-us
/// </remarks>
/// <param name="buffer">The array of bytes</param>
/// <param name="context">The response</param>
private static void WriteResponseInChunks(byte[] buffer, HttpContext context)
{
try
{
bool _continue;
context.Response.ClearContent();
context.Response.ContentType = "image/png";
using (var ms = new MemoryStream(buffer))
{
var dataToRead = buffer.Length;
while (dataToRead > 0)
{
if (context.Response.IsClientConnected)
{
{
var tmpBuffer = new byte[ChunkSize];
var length = ms.Read(tmpBuffer, 0, tmpBuffer.Length);
context.Response.OutputStream.Write(tmpBuffer, 0, length);
context.Response.Flush();
dataToRead -= length;
}
}
else
{
dataToRead = -1;
}
}
_continue = dataToRead > 0;
}
}
catch (Exception ex)
{
context.Response.ClearContent();
context.Response.ContentType = "text/plain";
context.Response.Write(string.Format("Error : {0}", ex.Message));
context.Response.Write(string.Format("Source : {0}", ex.Message));
context.Response.Write(string.Format("StackTrace: {0}", ex.StackTrace));
}
finally
{
context.Response.End();
}
}
/// <summary>
/// Gets a value indicating whether IsReusable
/// </summary>
public bool IsReusable
{
get
{
return true;
}
}
}
Maybe it will help if i just put up the code for creating the SharpMap.Map:
public static Map SqlServer(string conn, List<VectorLayerModel> layers, Size map_size, Envelope bbox, string id_column = "ID")
{
Map map = new Map(map_size);
foreach (var layer in layers)
{
VectorLayer lyr = CreateSqlServerLayer(conn, layer.Table, layer.Style, id_column);
lyr.IsQueryEnabled = true;
lyr.Enabled = true;
if (bbox != null)
{
var geometries = lyr.DataSource.GetGeometriesInView(bbox);
lyr.DataSource = new GeometryFeatureProvider(geometries);
}
map.Layers.Add(lyr);
}
return map;
}
After some debugging i found out that my
GetBoundingBoxInLatLngWithMargin(int tileX, int tileY, int zoom)
was returning bounds that was way out of my data bounds. I realized i was applying a coordinate transformation to my bbox giving me a bbox in pseudo mercator yet my layer is in wgs84. I changed the GetBoundingBoxInLatLngWithMargin to:
//code omited
Envelope bbox = new Envelope();
bbox.ExpandToInclude(ll1.X, ll1.Y );
bbox.ExpandToInclude(ll2.X, ll2.Y);
return bbox;
Please find the full conversation on GitHub
Has anyone found a good way to get auto-increment primary keys in a mocked context to work when testing service layers?
In most cases, seeding the primary key as part of the data to test is possible. But many service layer methods deal with creating multiple objects or linking other processes together that quickly fail if you are not responsible for passing all of the created data in. I thought of maybe adding a Callback() to SaveChangesAsync() that looks at the data created, and auto-generates a primary key incrementally but it won't be simple to implement.
var organization = new PrivateOrganization();
organization.Name = "New Test Organization";
organization.Description = "New Test Organization description";
organization.OrganizationTypeId = ITNOrganizationTypes.Agency;
organization.OrganizationStatusTypeId = (int)ITNOrganizationStatusTypes.Enabled;
organization.ShortCode = "Test";
var newOrg = await _service.InsertPrivateOrganizationAsync(organization);
_mockPrivateOrganizationsSet.Verify(m => m.Add(It.IsAny<PrivateOrganization>()), Times.Once());
MockTenantContext.Verify(m => m.SaveChangesAsync(), Times.Once());
// validation passes, but contains no auto-generated primary key.
I had to develop my own solution for this as follows:
/// <summary>
/// A helper class for managing custom behaviors of Mockable database contexts
/// </summary>
public static partial class EFSaveChangesBehaviors
{
/// <summary>
/// Enable auto-incrementing of primary key values upon SaveChanges/SaveChangesAsync
/// </summary>
/// <typeparam name="T">The type of context to enable auto-incrementing on</typeparam>
/// <param name="context">The context to enable this feature</param>
public static void EnableAutoIncrementOnSave<T>(this Mock<T> context) where T : DbContext
{
context.Setup(m => m.SaveChangesAsync())
.Callback(() =>
{
EFSaveChangesBehaviors.SaveChangesIncrementKey(context.Object);
})
.Returns(() => Task.Run(() => { return 1; }))
.Verifiable();
context.Setup(m => m.SaveChanges())
.Callback(() =>
{
EFSaveChangesBehaviors.SaveChangesIncrementKey(context.Object);
})
.Returns(() => { return 1; })
.Verifiable();
}
/// <summary>
/// Implements key incrementing of data records that are pending to be added to the context
/// </summary>
/// <param name="context"></param>
public static void SaveChangesIncrementKey(DbContext context)
{
var tablesWithNewData = GetUnsavedRows<DbContext>(context);
for (int i = 0; i < tablesWithNewData.Count; i++)
{
long nextPrimaryKeyValue = 0;
var tableWithDataProperty = tablesWithNewData[i];
var tableWithDataObject = tableWithDataProperty.GetValue(context);
if (tableWithDataObject != null)
{
var tableWithDataQueryable = tableWithDataObject as IQueryable<object>;
// 1) get the highest value in the DbSet<> (table) to continue auto-increment from
nextPrimaryKeyValue = IterateAndPerformAction(context, tableWithDataQueryable, tableWithDataProperty, nextPrimaryKeyValue, (primaryExistingKeyValue, primaryKeyRowObject, primaryKeyProperty) =>
{
if (primaryExistingKeyValue > nextPrimaryKeyValue)
nextPrimaryKeyValue = Convert.ToInt64(primaryExistingKeyValue);
return nextPrimaryKeyValue;
});
// 2) increase the value of the record's primary key on each iteration
IterateAndPerformAction(context, tableWithDataQueryable, tableWithDataProperty, nextPrimaryKeyValue, (primaryKeyExistingValue, primaryKeyRowObject, primaryKeyProperty) =>
{
if (primaryKeyExistingValue == 0)
{
nextPrimaryKeyValue++;
Type propertyType = primaryKeyProperty.PropertyType;
if (propertyType == typeof(Int64))
primaryKeyProperty.SetValue(primaryKeyRowObject, nextPrimaryKeyValue);
else if (propertyType == typeof(Int32))
primaryKeyProperty.SetValue(primaryKeyRowObject, Convert.ToInt32(nextPrimaryKeyValue));
else if (propertyType == typeof(Int16))
primaryKeyProperty.SetValue(primaryKeyRowObject, Convert.ToInt16(nextPrimaryKeyValue));
else if (propertyType == typeof(byte))
primaryKeyProperty.SetValue(primaryKeyRowObject, Convert.ToByte(nextPrimaryKeyValue));
else
throw new System.NotImplementedException($"Cannot manage primary keys of type: {propertyType.FullName}");
}
return nextPrimaryKeyValue;
});
}
}
}
/// <summary>
/// Get a list of properties for a data table that are indicated as a primary key
/// </summary>
/// <param name="t"></param>
/// <param name="context"></param>
/// <returns></returns>
/// <remarks>Reflection must be used, as the ObjectContext is not mockable</remarks>
public static PropertyInfo[] GetPrimaryKeyNamesUsingReflection(Type t, DbContext context)
{
var properties = t.GetProperties();
var keyNames = properties
.Where(prop => Attribute.IsDefined(prop, typeof(System.ComponentModel.DataAnnotations.KeyAttribute)))
.ToArray();
return keyNames;
}
/// <summary>
/// Iterates a table's data and allows an action to be performed on each row
/// </summary>
/// <param name="context">The database context</param>
/// <param name="tableWithDataQueryable"></param>
/// <param name="tableWithDataProperty"></param>
/// <param name="nextPrimaryKeyValue"></param>
/// <param name="action"></param>
/// <returns></returns>
private static long IterateAndPerformAction(DbContext context, IQueryable<object> tableWithDataQueryable, PropertyInfo tableWithDataProperty, long nextPrimaryKeyValue, Func<long, object, PropertyInfo, long> action)
{
foreach (var primaryKeyRowObject in tableWithDataQueryable)
{
// create a primary key for the object
if (tableWithDataProperty.PropertyType.GenericTypeArguments.Length > 0)
{
var dbSetType = tableWithDataProperty.PropertyType.GenericTypeArguments[0];
// find the primary key property
var primaryKeyProperty = GetPrimaryKeyNamesUsingReflection(dbSetType, context).FirstOrDefault();
if (primaryKeyProperty != null)
{
var primaryKeyValue = primaryKeyProperty.GetValue(primaryKeyRowObject) ?? 0L;
nextPrimaryKeyValue = action(Convert.ToInt64(primaryKeyValue), primaryKeyRowObject, primaryKeyProperty);
}
}
}
return nextPrimaryKeyValue;
}
/// <summary>
/// Get a list of objects which are pending to be added to the context
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="context"></param>
/// <returns></returns>
private static IList<PropertyInfo> GetUnsavedRows<T>(T context)
{
// get list of properties of type DbSet<>
var dbSetProperties = new List<PropertyInfo>();
var properties = context.GetType().GetProperties();
foreach (var property in properties)
{
var setType = property.PropertyType;
var isDbSet = setType.IsGenericType && (typeof(IDbSet<>).IsAssignableFrom(setType.GetGenericTypeDefinition()) || setType.GetInterface(typeof(IDbSet<>).FullName) != null);
if (isDbSet)
{
dbSetProperties.Add(property);
}
}
return dbSetProperties;
}
}
Usage:
// enable auto-increment in our in-memory database
MockTenantContext.EnableAutoIncrementOnSave();
I have a list of appointments, I would like to do a difference between the current appointment start time and last appointment end time to ensure there is no difference. If there is add a fake appointment.
My current implementation is...
public ObservableCollection<Appointment> FillGaps()
{
var appointments = this.Appointments.OrderByDescending(s => s.EndDate).ToList();
for (int i = 0; i < appointments.Count() - 1; i++)
{
var now = appointments[i];
var previous = appointments[i + 1];
if((now.StartDate.Value - previous.EndDate.Value).Days > 1)
{
// add a new appointment between this period
appointments.Add(new Appointment()
{
StartDate = previous.EndDate.Value.AddDays(1),
EndDate = now.StartDate.Value.AddDays(-1),
IsCurrent = false
});
}
}
return appointments.ToObservableCollection();
}
Is there a better or more generic way to do this?
As requested... Adding implementation of ToObservable...
/// <summary>
/// The to observable collection.
/// </summary>
/// <param name="coll">
/// The collection.
/// </param>
/// <typeparam name="T"> Object T
/// </typeparam>
/// <returns>
/// The <see cref="ObservableCollection"/>.
/// </returns>
public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> coll)
{
var c = new ObservableCollection<T>();
foreach (var e in coll)
{
c.Add(e);
}
return c;
}
Nothing special in Appointment class.
/// <summary>
/// The Appointment.
/// </summary>
[Serializable]
public class Appointment
{
public Appointment()
{
this.IsFake = false;
}
/// <summary>
/// Gets or sets the start date.
/// </summary>
public DateTime? StartDate { get; set; }
/// <summary>
/// Gets or sets the end date.
/// </summary>
public DateTime? EndDate { get; set; }
/// <summary>
/// Gets or sets the Is Fake
/// </summary>
public bool IsFake { get; set; }
}
Without knowing how the this.Appointments property is implemented, or what the parameter to the ToObservableCollection extension method is, it's difficult to come up with the most effective solution. However, something like this should work:
private static IEnumerable<Tuple<T, T>> ListPairs<T>(IEnumerable<T> source)
{
using (var enumerator = source.GetEnumerator())
{
if (!enumerator.MoveNext()) yield break;
T previous = enumerator.Current;
while (enumerator.MoveNext())
{
T current = enumerator.Current;
yield return new Tuple<T, T>(previous, current);
previous = current;
}
}
}
public ObservableCollection<Appointment> FillGaps()
{
var gaps = ListPairs(this.Appointments.OrderByDescending(s => s.EndDate))
.Where(pair => (pair.Item1.StartDate.Value - pair.Item2.EndDate.Value).Days > 1)
.Select(pair => new Appointment
{
StartDate = pair.Item2.EndDate.Value.AddDays(1),
EndDate = pair.Item1.StartDate.Value.AddDays(-1),
IsCurrent = false,
});
// NB: Assumes "this.Appointments" is a cheap call;
// Also assumes you don't need the results in any particular order.
return this.Appointments.Concat(gaps).ToObservableCollection();
}
Scenario
I've written a WMI Wrapper that seems to be quite sufficient, however whenever I run the code to start a remote process on a server, I see the process name appear in the task manager but the process itself does not start like it should (as in, I don't see the command line log window of the process that prints out what it's doing etc.)
The process I am trying to start is just a C# application executable that I have written.
Below is my WMI Wrapper Code and the code I am using to start running the process.
Question
Is the process actually running? - Even if it is only displaying the process name in the task manager and not actually launching the application to the users window?
Code To Start The Process
IPHostEntry hostEntry = Dns.GetHostEntry("InsertServerName");
WMIWrapper wrapper = new WMIWrapper("Insert User Name", "Insert Password", hostEntry.HostName);
List<Process> processes = wrapper.GetProcesses();
foreach (Process process in processes)
{
if (process.Caption.Equals("MyAppName.exe"))
{
Console.WriteLine(process.Caption);
Console.WriteLine(process.CommandLine);
int processId;
wrapper.StartProcess("E:\\MyData\\Data\\MyAppName.exe", out processId);
Console.WriteLine(processId.ToString());
}
}
Console.ReadLine();
WMI Wrapper Code
using System;
using System.Collections.Generic;
using System.Management;
using System.Runtime.InteropServices;
using Common.WMI.Objects;
using System.Net;
namespace Common.WMIWrapper
{
public class WMIWrapper : IDisposable
{
#region Constructor
/// <summary>
/// Creates a new instance of the wrapper
/// </summary>
/// <param jobName="username"></param>
/// <param jobName="password"></param>
/// <param jobName="server"></param>
public WMIWrapper(string server)
{
Initialise(server);
}
/// <summary>
/// Creates a new instance of the wrapper
/// </summary>
/// <param jobName="username"></param>
/// <param jobName="password"></param>
/// <param jobName="server"></param>
public WMIWrapper(string username, string password, string server)
{
Initialise(username, password, server);
}
#endregion
#region Destructor
/// <summary>
/// Clean up unmanaged references
/// </summary>
~WMIWrapper()
{
Dispose(false);
}
#endregion
#region Initialise
/// <summary>
/// Initialise the WMI Connection (local machine)
/// </summary>
/// <param name="server"></param>
private void Initialise(string server)
{
m_server = server;
// set connection options
m_connectOptions = new ConnectionOptions();
IPHostEntry host = Dns.GetHostEntry(Environment.MachineName);
}
/// <summary>
/// Initialise the WMI connection
/// </summary>
/// <param jobName="username">Username to connect to server with</param>
/// <param jobName="password">Password to connect to server with</param>
/// <param jobName="server">Server to connect to</param>
private void Initialise(string username, string password, string server)
{
m_server = server;
// set connection options
m_connectOptions = new ConnectionOptions();
IPHostEntry host = Dns.GetHostEntry(Environment.MachineName);
if (host.HostName.Equals(server, StringComparison.OrdinalIgnoreCase))
return;
m_connectOptions.Username = username;
m_connectOptions.Password = password;
m_connectOptions.Impersonation = ImpersonationLevel.Impersonate;
m_connectOptions.EnablePrivileges = true;
}
#endregion
/// <summary>
/// Return a list of available wmi namespaces
/// </summary>
/// <returns></returns>
public List<String> GetWMINamespaces()
{
ManagementScope wmiScope = new ManagementScope(String.Format("\\\\{0}\\root", this.Server), this.ConnectionOptions);
List<String> wmiNamespaceList = new List<String>();
ManagementClass wmiNamespaces = new ManagementClass(wmiScope, new ManagementPath("__namespace"), null); ;
foreach (ManagementObject ns in wmiNamespaces.GetInstances())
wmiNamespaceList.Add(ns["Name"].ToString());
return wmiNamespaceList;
}
/// <summary>
/// Return a list of available classes in a namespace
/// </summary>
/// <param jobName="wmiNameSpace">Namespace to get wmi classes for</param>
/// <returns>List of classes in the requested namespace</returns>
public List<String> GetWMIClassList(string wmiNameSpace)
{
ManagementScope wmiScope = new ManagementScope(String.Format("\\\\{0}\\root\\{1}", this.Server, wmiNameSpace), this.ConnectionOptions);
List<String> wmiClasses = new List<String>();
ManagementObjectSearcher wmiSearcher = new ManagementObjectSearcher(wmiScope, new WqlObjectQuery("SELECT * FROM meta_Class"), null);
foreach (ManagementClass wmiClass in wmiSearcher.Get())
wmiClasses.Add(wmiClass["__CLASS"].ToString());
return wmiClasses;
}
/// <summary>
/// Get a list of wmi properties for the specified class
/// </summary>
/// <param jobName="wmiNameSpace">WMI Namespace</param>
/// <param jobName="wmiClass">WMI Class</param>
/// <returns>List of properties for the class</returns>
public List<String> GetWMIClassPropertyList(string wmiNameSpace, string wmiClass)
{
List<String> wmiClassProperties = new List<string>();
ManagementClass managementClass = GetWMIClass(wmiNameSpace, wmiClass);
foreach (PropertyData property in managementClass.Properties)
wmiClassProperties.Add(property.Name);
return wmiClassProperties;
}
/// <summary>
/// Returns a list of methods for the class
/// </summary>
/// <param jobName="wmiNameSpace"></param>
/// <param jobName="wmiClass"></param>
/// <returns></returns>
public List<String> GetWMIClassMethodList(string wmiNameSpace, string wmiClass)
{
List<String> wmiClassMethods = new List<string>();
ManagementClass managementClass = GetWMIClass(wmiNameSpace, wmiClass);
foreach (MethodData method in managementClass.Methods)
wmiClassMethods.Add(method.Name);
return wmiClassMethods;
}
/// <summary>
/// Retrieve the specified management class
/// </summary>
/// <param jobName="wmiNameSpace">Namespace of the class</param>
/// <param jobName="wmiClass">Type of the class</param>
/// <returns></returns>
public ManagementClass GetWMIClass(string wmiNameSpace, string wmiClass)
{
ManagementScope wmiScope = new ManagementScope(String.Format("\\\\{0}\\root\\{1}", this.Server, wmiNameSpace), this.ConnectionOptions);
ManagementClass managementClass = null;
ManagementObjectSearcher wmiSearcher = new ManagementObjectSearcher(wmiScope, new WqlObjectQuery(String.Format("SELECT * FROM meta_Class WHERE __CLASS = '{0}'", wmiClass)), null);
foreach (ManagementClass wmiObject in wmiSearcher.Get())
managementClass = wmiObject;
return managementClass;
}
/// <summary>
/// Get an instance of the specficied class
/// </summary>
/// <param jobName="wmiNameSpace">Namespace of the classes</param>
/// <param jobName="wmiClass">Type of the classes</param>
/// <returns>Array of management classes</returns>
public ManagementObject[] GetWMIClassObjects(string wmiNameSpace, string wmiClass)
{
ManagementScope wmiScope = new ManagementScope(String.Format("\\\\{0}\\root\\{1}", this.Server, wmiNameSpace), this.ConnectionOptions);
List<ManagementObject> wmiClasses = new List<ManagementObject>();
ManagementObjectSearcher wmiSearcher = new ManagementObjectSearcher(wmiScope, new WqlObjectQuery(String.Format("SELECT * FROM {0}", wmiClass)), null);
foreach (ManagementObject wmiObject in wmiSearcher.Get())
wmiClasses.Add(wmiObject);
return wmiClasses.ToArray();
}
/// <summary>
/// Get a full list of services
/// </summary>
/// <returns></returns>
public List<Service> GetServices()
{
return GetService(null);
}
/// <summary>
/// Get a list of services
/// </summary>
/// <returns></returns>
public List<Service> GetService(string name)
{
ManagementObject[] services = GetWMIClassObjects("CIMV2", "WIN32_Service");
List<Service> serviceList = new List<Service>();
for (int i = 0; i < services.Length; i++)
{
ManagementObject managementObject = services[i];
Service service = new Service(managementObject);
service.Status = (string)managementObject["Status"];
service.Name = (string)managementObject["Name"];
service.DisplayName = (string)managementObject["DisplayName"];
service.PathName = (string)managementObject["PathName"];
service.ProcessId = (uint)managementObject["ProcessId"];
service.Started = (bool)managementObject["Started"];
service.StartMode = (string)managementObject["StartMode"];
service.ServiceType = (string)managementObject["ServiceType"];
service.InstallDate = (string)managementObject["InstallDate"];
service.Description = (string)managementObject["Description"];
service.Caption = (string)managementObject["Caption"];
if (String.IsNullOrEmpty(name) || name.Equals(service.Name, StringComparison.OrdinalIgnoreCase))
serviceList.Add(service);
}
return serviceList;
}
/// <summary>
/// Get a list of processes
/// </summary>
/// <returns></returns>
public List<Process> GetProcesses()
{
return GetProcess(null);
}
/// <summary>
/// Get a list of processes
/// </summary>
/// <returns></returns>
public List<Process> GetProcess(uint? processId)
{
ManagementObject[] processes = GetWMIClassObjects("CIMV2", "WIN32_Process");
List<Process> processList = new List<Process>();
for (int i = 0; i < processes.Length; i++)
{
ManagementObject managementObject = processes[i];
Process process = new Process(managementObject);
process.Priority = (uint)managementObject["Priority"];
process.ProcessId = (uint)managementObject["ProcessId"];
process.Status = (string)managementObject["Status"];
DateTime createDate;
if (ConvertFromWmiDate((string)managementObject["CreationDate"], out createDate))
process.CreationDate = createDate.ToString("dd-MMM-yyyy HH:mm:ss");
process.Caption = (string)managementObject["Caption"];
process.CommandLine = (string)managementObject["CommandLine"];
process.Description = (string)managementObject["Description"];
process.ExecutablePath = (string)managementObject["ExecutablePath"];
process.ExecutionState = (string)managementObject["ExecutionState"];
process.MaximumWorkingSetSize = (UInt32?)managementObject ["MaximumWorkingSetSize"];
process.MinimumWorkingSetSize = (UInt32?)managementObject["MinimumWorkingSetSize"];
process.KernelModeTime = (UInt64)managementObject["KernelModeTime"];
process.ThreadCount = (UInt32)managementObject["ThreadCount"];
process.UserModeTime = (UInt64)managementObject["UserModeTime"];
process.VirtualSize = (UInt64)managementObject["VirtualSize"];
process.WorkingSetSize = (UInt64)managementObject["WorkingSetSize"];
if (processId == null || process.ProcessId == processId.Value)
processList.Add(process);
}
return processList;
}
/// <summary>
/// Start the specified process
/// </summary>
/// <param jobName="commandLine"></param>
/// <returns></returns>
public bool StartProcess(string command, out int processId)
{
processId = int.MaxValue;
ManagementClass processClass = GetWMIClass("CIMV2", "WIN32_Process");
object[] objectsIn = new object[4];
objectsIn[0] = command;
processClass.InvokeMethod("Create", objectsIn);
if (objectsIn[3] == null)
return false;
processId = int.Parse(objectsIn[3].ToString());
return true;
}
/// <summary>
/// Schedule a process on the remote machine
/// </summary>
/// <param name="command"></param>
/// <param name="scheduleTime"></param>
/// <param name="jobName"></param>
/// <returns></returns>
public bool ScheduleProcess(string command, DateTime scheduleTime, out string jobName)
{
jobName = String.Empty;
ManagementClass scheduleClass = GetWMIClass("CIMV2", "Win32_ScheduledJob");
object[] objectsIn = new object[7];
objectsIn[0] = command;
objectsIn[1] = String.Format("********{0:00}{1:00}{2:00}.000000+060", scheduleTime.Hour, scheduleTime.Minute, scheduleTime.Second);
objectsIn[5] = true;
scheduleClass.InvokeMethod("Create", objectsIn);
if (objectsIn[6] == null)
return false;
UInt32 scheduleid = (uint)objectsIn[6];
jobName = scheduleid.ToString();
return true;
}
/// <summary>
/// Returns the current time on the remote server
/// </summary>
/// <returns></returns>
public DateTime Now()
{
ManagementScope wmiScope = new ManagementScope(String.Format("\\\\{0}\\root\\{1}", this.Server, "CIMV2"), this.ConnectionOptions);
ManagementClass managementClass = null;
ManagementObjectSearcher wmiSearcher = new ManagementObjectSearcher(wmiScope, new WqlObjectQuery(String.Format("SELECT * FROM Win32_LocalTime")), null);
DateTime localTime = DateTime.MinValue;
foreach (ManagementObject time in wmiSearcher.Get())
{
UInt32 day = (UInt32)time["Day"];
UInt32 month = (UInt32)time["Month"];
UInt32 year = (UInt32)time["Year"];
UInt32 hour = (UInt32)time["Hour"];
UInt32 minute = (UInt32)time["Minute"];
UInt32 second = (UInt32)time["Second"];
localTime = new DateTime((int)year, (int)month, (int)day, (int)hour, (int)minute, (int)second);
};
return localTime;
}
/// <summary>
/// Converts a wmi date into a proper date
/// </summary>
/// <param jobName="wmiDate">Wmi formatted date</param>
/// <returns>Date time object</returns>
private static bool ConvertFromWmiDate(string wmiDate, out DateTime properDate)
{
properDate = DateTime.MinValue;
string properDateString;
// check if string is populated
if (String.IsNullOrEmpty(wmiDate))
return false;
wmiDate = wmiDate.Trim().ToLower().Replace("*", "0");
string[] months = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
try
{
properDateString = String.Format("{0}-{1}-{2} {3}:{4}:{5}.{6}",
wmiDate.Substring(6, 2), months[int.Parse(wmiDate.Substring(4, 2)) - 1], wmiDate.Substring(0, 4), wmiDate.Substring(8, 2), wmiDate.Substring(10, 2), wmiDate.Substring(12, 2), wmiDate.Substring(15, 6));
}
catch (InvalidCastException)
{
return false;
}
catch (ArgumentOutOfRangeException)
{
return false;
}
// try and parse the new date
if (!DateTime.TryParse(properDateString, out properDate))
return false;
// true if conversion successful
return true;
}
private bool m_disposed;
#region IDisposable Members
/// <summary>
/// Managed dispose
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Dispose of managed and unmanaged objects
/// </summary>
/// <param jobName="disposing"></param>
public void Dispose(bool disposing)
{
if (disposing)
{
m_connectOptions = null;
}
}
#endregion
#region Properties
private ConnectionOptions m_connectOptions;
/// <summary>
/// Gets or sets the management scope
/// </summary>
private ConnectionOptions ConnectionOptions
{
get
{
return m_connectOptions;
}
set
{
m_connectOptions = value;
}
}
private String m_server;
/// <summary>
/// Gets or sets the server to connect to
/// </summary>
public String Server
{
get
{
return m_server;
}
set
{
m_server = value;
}
}
#endregion
}
}
It is running but it's not running interactive. If you're running a process remotely you can't be sure that someone is even logged in to that pc so you can't assume that it can have a GUI that a user can interact with.
I'd suggest, instead of writing progress to the console window, write it to a file or the Event log.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I wrote this piece of code to merge two .NET configuration files: Add non existent nodes and override values on existing ones.
I avoided to use the much faster reader/writer way because the app I'm using it for is not performance critical. What do you think of this?
using System;
using System.Xml;
namespace devcoach.FrameworkExtensions
{
/// <summary>
/// Extension methods for the type
/// <see cref="System.Xml.XmlDocument"/>.
/// </summary>
public static class XmlDocumentExtensions
{
/// <summary>
/// Merges the specified instance.
/// </summary>
/// <param name="instance">The instance.</param>
/// <param name="mergeDoc">The merge doc.</param>
public static void Merge(
this XmlDocument instance,
XmlDocument mergeDoc)
{
var mergeRoot = mergeDoc.DocumentElement;
var sourceRoot = instance.DocumentElement;
if (sourceRoot == null) return;
instance.Merge(sourceRoot, mergeRoot, false);
}
/// <summary>
/// Merges the specified instance.
/// </summary>
/// <param name="instance">The instance.</param>
/// <param name="mergeDoc">The merge doc.</param>
/// <param name="isNetConfigFile">if set to <c>true</c> if documents
/// are .net config files.</param>
public static void Merge(
this XmlDocument instance,
XmlDocument mergeDoc,
bool isNetConfigFile)
{
var mergeRoot = mergeDoc.DocumentElement;
var sourceRoot = instance.DocumentElement;
if (sourceRoot == null) return;
instance.Merge(sourceRoot, mergeRoot, true);
}
/// <summary>
/// Merges the specified source doc.
/// </summary>
/// <param name="sourceDoc">The source doc.</param>
/// <param name="sourceRoot">The source root.</param>
/// <param name="mergeRoot">The merge root.</param>
public static void Merge(
this XmlDocument sourceDoc,
XmlNode sourceRoot,
XmlNode mergeRoot)
{
sourceDoc.Merge(
sourceRoot,
mergeRoot,
false);
}
/// <summary>
/// Merges the specified source doc.
/// </summary>
/// <param name="sourceDoc">The source doc.</param>
/// <param name="sourceRoot">The source root.</param>
/// <param name="mergeRoot">The merge root.</param>
/// <param name="isNetConfigFile">if set to <c>true</c> if documents
/// are .net config files.</param>
public static void Merge(
this XmlDocument sourceDoc,
XmlNode sourceRoot,
XmlNode mergeRoot,
bool isNetConfigFile)
{
#region Check parameters and if needed throw ArgumentNullException
if (sourceDoc == null)
{
throw new ArgumentNullException("sourceDoc");
}
if (sourceRoot == null)
{
throw new ArgumentNullException("sourceRoot");
}
if (mergeRoot == null)
{
throw new ArgumentNullException("mergeRoot");
}
#endregion
if (!string.IsNullOrEmpty(mergeRoot.InnerText))
{
sourceRoot.InnerText = mergeRoot.InnerText;
}
if (!string.IsNullOrEmpty(mergeRoot.Value))
{
sourceRoot.Value = mergeRoot.Value;
}
#region Copy attributes...
var mergeRootAttributes = mergeRoot.Attributes;
if (mergeRootAttributes != null)
{
var mergeRootAttributesCount = mergeRootAttributes.Count;
for (var k = 0; k < mergeRootAttributesCount; k++)
{
var mergeAttribute = mergeRootAttributes[k];
var mergeAttributeName = mergeAttribute.LocalName;
var sourceAttribute =
sourceRoot.Attributes[mergeAttributeName]
?? sourceRoot.Attributes.Append(
sourceDoc.CreateAttribute(
mergeAttribute.Prefix,
mergeAttribute.LocalName,
mergeAttribute.NamespaceURI));
sourceAttribute.Value = mergeAttribute.Value;
}
}
#endregion
// loop child nodes...
var mergeRootNodesCount = mergeRoot.ChildNodes.Count;
for (var i = 0; i < mergeRootNodesCount; i++)
{
XmlNode foundNode = null;
var mergeNode = mergeRoot.ChildNodes[i];
var mergeNodeName = mergeNode.LocalName;
var sourceRootNodeCount = sourceRoot.ChildNodes.Count;
#region Find node in source...
for (var j = 0; j < sourceRootNodeCount; j++)
{
var sourceNode = sourceRoot.ChildNodes[j];
var sourceNodeName = sourceNode.LocalName;
if ((isNetConfigFile &&
mergeNodeName == "section" ||
mergeNodeName == "sectionGroup"
) ||
sourceNodeName != mergeNodeName) continue;
foundNode = sourceNode;
break;
}
#endregion
#region create a new node...
if (foundNode == null)
{
foundNode =
sourceRoot.AppendChild(
sourceDoc.CreateNode(
mergeNode.NodeType,
mergeNode.Prefix,
mergeNode.LocalName,
mergeNode.NamespaceURI));
}
#endregion
sourceDoc.Merge(foundNode, mergeNode);
}
}
}
}
You can also take a look on XmlMassUpdate task of the http://msbuildtasks.tigris.org/ it do the same thing...
If it works for you...
You should take a look at Linq to XML. It's much better than System.XML: Cleaner code, easier to write code, easier to understand code, less code. Lovely.