I am writing an application to record some hardware information of computers in our environment and I am unclear on an enum mapping from the Win32/CIM/WMI(?) API. I am getting VideoOutputTechnology from the root/wmi/wmimonitorconnectionparams class using the Microsoft.Management.Infrastructure library. This value is UInt32 enum - the source is visible here.
I have successfully mapped most of this to a C# enum, but I am unclear on how I would write out the last five values (see below). Is it true that D3DKMDT_VOT_SVIDEO_4PIN = D3DKMDT_VOT_SVIDEO = 1?
D3DKMDT_VOT_SVIDEO = 1,
D3DKMDT_VOT_COMPOSITE_VIDEO = 2,
D3DKMDT_VOT_COMPONENT_VIDEO = 3,
// omitted for brevity
D3DKMDT_VOT_SVIDEO_4PIN = D3DKMDT_VOT_SVIDEO,
D3DKMDT_VOT_SVIDEO_7PIN = D3DKMDT_VOT_SVIDEO,
D3DKMDT_VOT_RF = D3DKMDT_VOT_COMPOSITE_VIDEO,
D3DKMDT_VOT_RCA_3COMPONENT = D3DKMDT_VOT_COMPONENT_VIDEO,
D3DKMDT_VOT_BNC = D3DKMDT_VOT_COMPONENT_VIDEO,
My version of this code looks similar to the following:
public enum WmiMonitorConnectionParamsVideoOutputTechnology : uint
{
SVideo = 1,
CompositeVideo = 2,
ComponentVideo = 3,
// Is this correct?
SVideo4Pin = WmiMonitorConnectionParamsVideoOutputTechnology.SVideo,
SVideo7Pin = WmiMonitorConnectionParamsVideoOutputTechnology.SVideo,
RF = WmiMonitorConnectionParamsVideoOutputTechnology.CompositeVideo,
RCA_3COMPONENT = WmiMonitorConnectionParamsVideoOutputTechnology.ComponentVideo,
BNC = WmiMonitorConnectionParamsVideoOutputTechnology.ComponentVideo,
}
I realize that this appears to be an Int32 type in this source code, but it's coming from CIM as UInt32. However, that does not change my question on mapping these enum values
I found this information here.
Frankly, I'm not really sure what I'm looking at so I'm having trouble phrasing a question on Google to get the right answer.
Related
I have a property LegalCaseStatus. My intention is to make the property to accept a predefined range of approved values. The range must be visible and unchanged throughtout my program. Here's an example of the list:
Plaintiff
Defendant
Third Party
Debitor
Creditor
Petitioner
So, the best way I could think of is to declare a static class, and fill it with corresponding constants:
public static class Participants
{
public const byte
Piaintiff = 0,
Defendant = 1,
ThirdParty = 2,
Debitor= 3,
Creditor = 4,
Petitioner = 5;
}
so after using a namespace I could just do:
public byte LegalCaseStasus = Plaintiff;
the only problem is, since it's just a byte member it'll accept anything that is byte:
LegalCaseStatus = 99; // ok
LegalCaseStatus = SomeOtherByteConstant; // ok
How do I protect the member LegalCaseStatus? Is my solution generally correct?
You can use enums - An enum is a special "class" that represents a group of constants (unchangeable/read-only variables). Sounds like the thing you describe in your question:
public enum Participants
{
Piaintiff = 0,
Defendant = 1,
ThirdParty = 2,
Debitor = 3,
Creditor = 4,
Petitioner = 5
}
After the enum definition you can use it exactly the way you want to:
Participants LegalCaseStasus = Participants.ThirdParty;
LegalCaseStasus = 99; // ERROR
byte underlying_value = (byte)LegalCaseStasus; // value == 2
Note: The underlying value of an enum is int! When you cast to byte you need to make sure there are no predefined values that exceed the byte limit.
I'm trying to update existing entry in Feature Table in MSI. More specifically, the Feature Identifier itself (first column - Feature).
String featureQuery = "SELECT * FROM `Feature`";
view = db.OpenView(featureQuery);
view.Execute();
rec = view.Fetch();
rec.SetString("Feature", "NewName"); <- error here "Function failed during execution"
view.Modify(ViewModifyMode.Update, rec);
However, when I do the same but only change "Feature" column to "Title" (in row where error occurs) for example, title column in MSI is changing to "NewName".
So, my question is - does this even possible or I'm making mistake somewhere? If later, please point me where, I would be very grateful. Anyway, any suggestions are very appreciated, thanks!
This example of mine isn't exactly the same because it's my dumb C# P/Invoke test, but it does work and change the Feature.Feature value, so it is allowed by the APIs, and perhaps there's something that the DTF wrapper classes have in the way of defaults etc that needs changing. The obvious difference is in the SetString/MsiRecordSetString code where the native API requires a field number. I apologize for not looking at the DTF, but SetString presumably maps the "Feature" string to an actual field number to update the first field of the record. If it has an overload that takes a field number, try that one. I'll add that you haven't actually selected a specific feature, so you're at risk of modifying the "first" feature, because select * will return them all.
IntPtr hDb = IntPtr.Zero;
int res = MsiInvoke.MsiOpenDatabase("C:\\Phil\\MyDD\\Samples Setup\\InsertRTF\\setup.msi", MsiInvoke.MSIDBOPEN_TRANSACT, out hDb);
string qinsert = "SELECT * FROM `Feature`";
IntPtr hView =IntPtr.Zero;
res = MsiInvoke.MsiDatabaseOpenView(hDb, qinsert, out hView);
res = MsiInvoke.MsiViewExecute(hView, 0);
IntPtr hRec= IntPtr.Zero;
res = MsiInvoke.MsiViewFetch(hView, out hRec);
res = MsiInvoke.MsiRecordSetString(hRec, 1, "Whatever");
res = MsiInvoke.MsiViewModify(hView, 4, hRec); // 4 = msimodify_replace 3 = modify_assign
res = MsiInvoke.MsiViewClose(hView);
res = MsiInvoke.MsiDatabaseCommit(hDb);
MsiInvoke is just a dumb P/invoke class I created, starting like this:
public class MsiInvoke
{
//Oops MSIHandles are not IntPtrs.
[DllImport("msi", CharSet = CharSet.Auto)]
public static extern int MsiOpenDatabase(string filename, int persist, out IntPtr dbhandle);
public const int MSIDBOPEN_DIRECT = 2;
public const int MSIDBOPEN_TRANSACT = 1;
I have a question that I'm sure has already been answered. Any help pointing me in the right direction would be appreciated.
I have a standard ASP MVC site. As with any site, I have the usual collection of key values for various aspects of the application.
Hair Color
10 = Green
20 = Brown
...
Status
10 = Active
20 = Paused
99 = Inactive
...
SubscriptionType
10 = 1 Week
20 = 1 Month
30 = 3 Month
...
Approval
0 = Pending Approval
10 = Approved
20 = Approved with Conditions
99 = Rejected
etc..etc..etc...
Normally, I have a bunch of DB tables associated with the various types but I find all the overall management of this method tedious (creating, adding values, SQL calls)
My question:
Is there a simple and straightforward way of defining and accessing these key values within the MVC code itself. I know I can use various means (Lists, Dictionary, Hashtables, Enums, etc..) but I'm looking for something that I can easily access across various Controllers AND Views (in some Common Helper class?). I want to be able to get the value from the key OR the reverse and get the key from the value.
I know there are probably 1000 ways to skin this cat but I'd be interested if anyone could point me to a simple and straightforward way to do it. Is this something that could (or should) be done in the Model layer? A Helper "CommonValues" class? Any suggestions would be welcome.
Apologies if this is "Programming 101" stuff. (I'm self taught)
For integers
You can use an enum, like this:
enum SubscriptionType
{
OneWeek = 10,
OneMonth = 20,
ThreeMonths = 30
}
You could certainly define your enums as members of a CommonValues class, if you have one. Or you could define them within the namespace and outside of any class, which would make them globally available.
For strings (or integers if you like this method better)
You can define constants as a member of a class. Constants are exposed as static fields so they are accessible anywhere.
public class CommonValues
{
public const string ColorRed = "RED";
public const string ColorBlue = "BLUE";
public const string WorkflowStateStopped = "STOPPED";
public const string WorkflowStateRunning = "RUNNING";
}
//Main program
var a = CommonValues.ColorRed;
var b = CommonValues.WorkflowStateRunning;
Notice the messy "ColorXXX" pattern. Seems a little 90s to me. If you want to restrict namespaces so your intellisense works a bit more usefully, you can use a nested class.
public class CommonValues
{
public class Colors
{
public const string Red = "RED";
public const string Blue = "BLUE";
}
public class WorkflowStates
{
public const string Running = "RUNNING";
public const string Stopped = "STOPPED";
}
}
//Main program
var b = CommonValues.Colors.Red;
var c = CommonValues.WorkflowStates.Running;
Display
When it comes to display the meaning of one of these codes, naturally your display elements should come from resources, which will automatically adapt to the current culture (after all, some day you will be an international giant). You can organize your resources with names like this:
var resources = new ResourceManager("CommonValues", myAssembly);
//Example for use with enum
SubscriptionType code = SubscriptionType.OneWeek;
var display = resources.GetString("SubscriptionType." + code.ToString()); //Resource ID = "SubscriptionType.OneWeek";
//Example for use with string constant
var colorCode = CommonValues.Colors.Red;
var display = resources.GetString("Colors." + colorCode); //Resource ID = "Colors.Red";
I wanted to put in some details of what I did in case this helps others down the line. Using John Wu's answer from above (thanks!!), here's what I did.
Create the enum. You need to put this in some class that you can reference in the View. I called mine EnumValues in the EnumHelper namespace.
namespace MyProject.EnumHelper
{
public static class EnumValues
{
public enum ProjectStatus
{
Active = 10,
Paused = 20,
Inactive = 99
}
...
So the beginning of my View looks like
#using MyProject.EnumHelper;
#model MyProject.Models.ProjectViewModel;
...
Now, if I have the integer value (say from the DB call) and I want the decoded string (ex. "Active"), I did this in the view.
var projectstatus = (EnumValues.ProjectStatus)Model.project_status;
If I need to get the enum integer value (ex. in a dropdown), I did this in the view.
var projectstatusid = (int)EnumValues.ProjectStatus.Active;
Thanks again to John Wu for pointing me in the right direction.
In my project i am using an Array of bool which defines the user's access rights.
For example
public bool[] Security {get; set;}
where
[0] = Admin
[1] = GrantWrites
[2] = GrantDeletes
[3] = User
It is working quite well.
I would set it to {F,T,F,T} or {0,1,0,1} and that particular user gets access as a User and it allows him to write.
I am trying to convert it to an enum but apparently i would need an array of it.
currently i have the following (not working)
public class UserCrops
{
public UserCrops(etc.., Enum[] _Security)
{
.
.
.
Security = _Security;
}
.
.
.
public Enum[] Security
{
Admin,
GrantWrites,
GrantDeletes,
User
}
}
I found some links like this but no help.
Thanks in advance
Edit: Both answers are very well explained but I am going with the non-Flag one just because it seems easier for me :)
Edit2: How can i create a new object (outside of class?)
I used to do
bool[] security = new bool[9];
for (int i = 0; i < 9; i++)
{
security[i] = chklstSecurity.Items[i].Selected;
}
userCropList.Add(new UserCrops(.., txtBiologicalAssessmentApprovalDate.Text, security));
But now?
Try with:
[Flags]
public enum Security
{
Admin = 1,
GrantWrites = 2,
GrantDeletes = 4,
User = 8
}
And you'll use it like this:
Security security = Security.GrantWrites | Security.GrantDeletes;
if ((security & Security.GrantWrites) == Security.GrantWrites)
{
}
Comparison can be simplified as pointed out by p.s.w.g. to increase its readability. Moreover I suggest to include a default value in the enum (for when variable is not initialized):
[Flags]
public enum Security
{
None = 0,
Admin = 1,
GrantWrites = 2,
GrantDeletes = 4,
User = 8
}
Finally note that you can provider shortcut for common combinations of flags:
[Flags]
public enum Security
{
// Other values
FullAccess = Admin | GrantWrites | GrantDeletes
}
More of that on MSDN. Please note this approach mimics attributes for file/directories in file system (and many other). IMO is much simpler to use than keep an array of enums as suggested in the other answer:
You do not have to search entire array to check if a permission is granted or not.
You do not have to check for a null value (enum can't be null, an array can be).
It uses less space (even if nowadays this is not so important).
It's naturally (more) safe so less checks are needed (for example to avoid duplicates inside array).
It can be easy stored (as text or integer without additional code).
But it has, compared to that, two main drawbacks:
Flags are finite (32 if you're using an Int32 for your enum or 64 for an Int64).
You can't easily switch to something else (if, for example, Security has to become a class you'll need to write much more code to mimic enums syntax and some assumption made by code when working with enums will be broken).
Remove the [] and use enum instead of Enum:
public enum Security
{
Admin,
GrantWrites,
GrantDeletes,
User
}
And you probably want to use Security[] as a method parameter:
public UserCrops(etc.., Security[] _Security)
Using flags (as Adriano suggests) is an excellent suggestion too, but it will require you to rethink how you're storing your permissions. Instead of storing an array of bool's, you'll represent the entire security set as a single value, with different bits representing each permission.
Read Enumeration Types (C# Programming Guide) under the section Enumeration Types as Bit Flags for more information.
Hi before going to direct problem let me show my code :
//Definition of enum
public enum LogType
{
Warning = -2,
Error = -1,
Info = 0,
EruCtorDtor = 1,
Notifications = 2,
CommunicationWithAOT = 4,
ExecutedOrder = 8,
ERUInfo = 16,
DebugLog = 32,
}
//Use of enum
CurrentLogFlagSettings = nLogFlag;
LogFlagMap = new SortedDictionary<LogType, int>();
ulong mask = 1;
while(mask <= nLogFlag)
{
if ((nLogFlag & mask) == mask)
{
LogType type = (LogType)mask; //Step 1
string val = type.ToString(); //Step 2
//Processing the value
LogFlagMap.Add(type, tempVal)
LogMsg(val + " added", type);
}
mask <<= 1;
}
What I want is : Process step2 only after step1 has produced valid value. I mean value should be between range defined in enum definition. Otherwise I dont want to process it.
for e.g.
case 1 - Lets say mask value is 32,
its defined in enum. So type is
getting value DebugLog and so it
type.ToString() (i.e. "DebugLog"),
this is a valid case.
case 2- Lets
say mask value is 128 and its not
defined in enum, in this case I dont
want to process anything on 128
value. But what is happening its
geting value 128 in type and
type.ToString() is converting it
into 128. I dont want this, I want
to make sure whether 128 belongs to
enum values or not.
I want to prevent 2nd case to be executed. Is there any solution for my problem?
Please let me know if more details are needed.
You could use Enum.IsDefined, like so:
int value = 128;
Console.WriteLine(Enum.IsDefined(typeof(LogType), value)); // will print out False
Firstly, let me seriously apologise, Ive had like no sleep, so if I missed the point a little. Please, just ignore me.
You can enumerate your LogType with Enum.GetValues(typeof(LogType))), so you could step through and check a value against it. I had some code, but, I couldnt promise it compiled.
Bool isValid(int i)
{
foreach (LogType l in Enum.GetValues(typeof(LogType)))
{
if ((int)l == i) return true;
}
return false;
}
You can also use Enum.GetValues(typeof(LogType)) to get all the possible values for your enum and do what you want through that.
i.e.
var values = Enum.GetValues(typeof (LogType));
foreach (LogType type in values)
{
if (((int)type & nLogMask) == (int)type)
{
//value is valid, process the value
}
}
One addition to your code could be the addition of the [Flags] attribute to you enum, this then makes it clear that the enum values are for bitwise operations
e.g.
[Flags]
public enum LogType
{
Warning = -2,
Error = -1,
Info = 0,
EruCtorDtor = 1,
Notifications = 2,
CommunicationWithAOT = 4,
ExecutedOrder = 8,
ERUInfo = 16,
DebugLog = 32,
}
although to do this, you would need to change the values such that the Warning and Error take the top 2 bits of the enum value (assuming this is still necessary).
The c# Enum class also has the method GetName(). This might provide a nice and easy manner to retrieve the name of the value set
e.g.
Enum.GetName( typeof(LogType), 4 ); // result = CommunicationWithAOT
I have a library called Unconstrained Melody which allows you to express all of this in a type-safe generic way and avoids boxing too. Personally I prefer that over using Enum.IsDefined, but obviously that doesn't involve learning an extra library.
It's probably not worth using Unconstrained Melody if this is the only thing you need to do with your enum, but if you've got other similar operations, you may wish to consider it.