|
The purpose of interfaces is to allow you to specify a certain "language" for objects so others will know how to talk to it. What I mean by this is, if I have an IDataEngine interface, then I can specify what public properties and methods it must have. Then, I (or another developer) could reuse this for multiple data engines. For instance, say there was a need for an XmlEngine and a ServiceEngine . They'll both use the same methods so the client using them knows how to talk to them, but each would have it's own implementation. Obviously in this example, the former would talk to XML files and the latter would talk to services.
Try to take the time to understand the Command Pattern [^]. If you can get around some of the things that try to make it complex, this pattern should provide a good basis for interfaces. There are plenty others, but if this one doesn't get it for you, try the Abstract Factory Pattern[^].
Good luck!
Michael Flanakin
Web Log
|
|
|
|
|
I'd like to write a small app that will show which users have a certain file locked similiar to Win2k/XP's Computer Management. I thought WMI might work for this but I'm not sure what class to use.
Can anyone give me some suggestions on how to accomplish this using VB.NET/C#?
Thanks.
-Mike
|
|
|
|
|
If you're talking about those files that are open across network shares, you can use the following code since WMI doesn't expose these handles (that I can find or already know about):
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct FileInfo
{
[MarshalAs(UnmanagedType.U4)]public int ID;
[MarshalAs(UnmanagedType.U4)]public FilePermissions Permissions;
[MarshalAs(UnmanagedType.U4)]public int Locks;
[MarshalAs(UnmanagedType.LPWStr)]public string Path;
[MarshalAs(UnmanagedType.LPWStr)]public string Username;
}
[Flags]
public enum FilePermissions
{
Read = 1,
Write = 2,
Create = 4
}
public class NetFiles
{
private const int ErrorFileNotFound = 2;
private const int ErrorAccessDenied = 5;
private const int ErrorMoreData = 234;
private const int MaxPreferredLength = -1;
private const int BufferSize = 4000;
[DllImport("netapi32.dll", CharSet=CharSet.Unicode)]
private static extern int NetFileEnum
(
[MarshalAs(UnmanagedType.LPWStr)]string serverName,
[MarshalAs(UnmanagedType.LPWStr)]string basePath,
[MarshalAs(UnmanagedType.LPWStr)]string userName,
[MarshalAs(UnmanagedType.U4)]int level,
[MarshalAs(UnmanagedType.SysUInt), Out]out IntPtr buffer,
[MarshalAs(UnmanagedType.U4)]int preferredMaxLength,
[MarshalAs(UnmanagedType.U4), Out]out int entriesRead,
[MarshalAs(UnmanagedType.U4), Out]out int totalEntries,
[MarshalAs(UnmanagedType.U4), In, Out]ref int resumeHandle
);
[DllImport("netapi32.dll", CharSet=CharSet.Unicode)]
private static extern int NetFileClose
(
[MarshalAs(UnmanagedType.LPWStr)]string serverName,
[MarshalAs(UnmanagedType.U4)]int fileID
);
[DllImport("netapi32.dll")]
private static extern int NetApiBufferFree
(
IntPtr buffer
);
private NetFiles()
{
}
public static IList GetOpenFiles()
{
return GetOpenFiles(null, null, null);
}
public static IList GetOpenFilesOnServer(string server)
{
return GetOpenFiles(server, null, null);
}
public static IList GetOpenFilesWithPath(string basePath)
{
return GetOpenFiles(null, basePath, null);
}
public static IList GetOpenFilesForUsername(string username)
{
return GetOpenFiles(null, null, username);
}
public static IList GetOpenFiles(string server, string basePath,
string username)
{
IntPtr buffer;
int entriesRead;
int totalEntries;
int resumeHandle = 0;
ArrayList list = new ArrayList();
int retVal = NetFileEnum(server, basePath, username, 3, out buffer,
BufferSize, out entriesRead, out totalEntries, ref resumeHandle);
while ((retVal == 0 || retVal == ErrorMoreData) && buffer != IntPtr.Zero)
{
for (int i=0; i<entriesRead; i++)
{
IntPtr address = new IntPtr(buffer.ToInt32() + i *
Marshal.SizeOf(typeof(FileInfo)));
if (address != IntPtr.Zero)
{
FileInfo info = (FileInfo)Marshal.PtrToStructure(address,
typeof(FileInfo));
list.Add(info);
}
}
NetApiBufferFree(buffer);
if (retVal == ErrorMoreData)
retVal = NetFileEnum(server, basePath, username, 3, out buffer,
MaxPreferredLength, out entriesRead, out totalEntries, ref resumeHandle);
else break;
}
if (retVal == 0) return list;
else if (retVal == 5) throw new SecurityException("Access denied");
else throw new System.ComponentModel.Win32Exception(retVal);
}
public static void CloseFile(int handle)
{
CloseFile(handle, null);
}
public static void CloseFile(int handle, string server)
{
int retVal = NetFileClose(server, handle);
if (retVal == 0) return;
else if (retVal == ErrorAccessDenied)
throw new SecurityException("Access denied");
else if (retVal == ErrorFileNotFound)
throw new System.IO.FileNotFoundException("The file was not found.");
else throw new System.ComponentModel.Win32Exception(retVal);
}
} This is just part of an in-house application I wrote and I offer no warranty of any kind. Use it as an example.
To get open file handles on the local machine is much more difficult and uses a bunch of undocumented APIs. I haven't figured out what exactly to pass for parameters. You can, however, find an application that does this called "Handle" on http://www.sysinternals.com[^].
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Many thanks. I'll give this a shot today.
|
|
|
|
|
Hello,
First, Thanks for that post!
Heath Stewart wrote: To get open file handles on the local machine
I'm facing exactly this problem write now:
http://www.codeproject.com/script/comments/forums.asp?msg=2086842&forumid=1649#xx2086842xx[^]
Heath Stewart wrote: uses a bunch of undocumented APIs
Maybe you can point some of them out to help me a little more?
Heath Stewart wrote: You can, however, find an application that does this called "Handle" on http://www.sysinternals.com[^].
Had no luck searching!
Thanks for your time!
All the best,
Martin
|
|
|
|
|
I have a C# .Net windows service that I am developing and have the installation of it on my machine working fine. It starts up and runs as expected as just a simple skeleton of what I want it to do.
My issue is that I want to use the same executable of the application to run as separate service instances based on startup parameters passed into the service via another application or by manual startup. The code will all work the same but will connect and be running connected to different databases for each instance that is running as a service.
I see in all the examples that the 'this.ServiceName' property is set in the InitializeComponents method, but I want to use the parameters passed into OnStart(string[] args) to let me determine what service it is going to be running as.
The way it looks now is that I will have to hardcode the 'this.serviceInstaller1.ServiceName', the 'this.ServiceName' and the application executable to have separate services for each of the databases that I want to connect.
Doesn't the application know the SCM service entry that is invoked to start up the process without explicitly setting it?
Is there not a way to do this dynamically?
Please advise
Regards,
Craig in Boise, ID
|
|
|
|
|
The problem with using OnStart's parameters is that the SCM is already starting the service at that point, and must have discovered the name beforehand.
My company currently has a few exes which we run as multiple services on the same machine. Our design goals caused us to end up with multiple copies of the exe (different file names). Each are registered individually as services, which includes the exe name as part of the name of the service. With this setup, the service installer and the service itself can both determine the proper service name by detecting the name of the running executable.
You may be able to modify the installer to check for certain parameters at the time that the service is registered, then pass those same parameters to the exe when the service is started. It doesn't seem impossible, but the key is to distinguish between services at installation time.
John
"You said a whole sentence with no words in it, and I understood you!" -- my wife as she cries about slowly becoming a geek.
|
|
|
|
|
I'm strugging to get the BindtoObject method of the IShellInterface working, but it throws errors no matter what I do.
At first i thought it was a design problem, where i was using the wrong PIDL. But i pulled the display name from it, and parsed that for a pointer, and it still isn't working, so i'm somewhat baffled.
here is the method as i've written it:
[PreserveSig]<br />
int BindToObject( <br />
IntPtr pidl,<br />
IntPtr pbc,<br />
Guid riid,<br />
out IntPtr ppv);
When i call the method, i call it as follows:
DesktFolderInterface.BindToObject(FolderPIDL, IntPtr.Zero, IShellGUID, out pFolderInteraface);
where the Desktop folder is the object i'm calling the bind from. The FolderPIDL i have tried as both the return from the SHBrowseForFolder dialog, and then by parsing the name of the folder retrieved from the dialog. Neither of which succeeded.
The GUID is the GUID value for IShellFolder, retrieved by this line:
Guid IShellGUID = Marshal.GenerateGuidForType(shellType);
For the pbc value, i've used both IntPtr.zero, and a variable defined as IntPtr.zero.
I'm not sure why this won't work, but i thought it was a layout mistake at first, now i'm not so sure.
Can anyone help?
Cheers
Cata
[Edit]: I've used all these components in a different COM method, and they worked fine, so i know that the components are all valid. Which is why it is confusing that it does not work.
|
|
|
|
|
I've found some sample code that showed BindToObject as using a ref GUID, rather than an unrefferenced. This now works, but i have no idea why.
Could anyone shed any light on this?
Cheers
Cata
|
|
|
|
|
Guid is a value type (a struct ), not a reference type (a class ). In the original code (not using ref ) the marshaller tries to pass the IID by value, which isn't compatible with the interface.
The BindToObject method takes a REFIID in the unmanaged interface, so needs to be matched with a ref Guid in the managed interface.
Stability. What an interesting concept. -- Chris Maunder
|
|
|
|
|
I figured that out, while it WAS working with ref, i also got it working without the ref using MarshalAs(UnmanagedType.LPStruct).
But thanks all the same, it clears up a few holes in my thinking.
Cata
|
|
|
|
|
Hi. This is probably real easy, but I just can't seem to figure it out. I have a dataset that returns a unique value. I would like to move that value to a textbox. No matter what I try, I can't get my code to fill the textbox.
I use a dataadapter, dataset, sqlcommand and sqlparm to read a sql2000 stored procedure. I put in the city name and get out the unique city id number we use. I've run teh stored procedure separately and I know it works. Do I databind the textbox to the dataset?
This is the code I'm currently using:
da = new SqlDataAdapter("ap_prs_frm_addr_urbn_cmty_id", addr_urbn_conn);
da.SelectCommand.CommandType = CommandType.StoredProcedure;
ds = new DataSet();
SqlParameter addr_urbn_parm;
addr_urbn_parm = new SqlParameter("@cmty_desc", System.Data.SqlDbType.VarChar);
addr_urbn_parm.Direction = ParameterDirection.Input;
addr_urbn_parm.Value = ddlAddrUrbnCmty.SelectedItem.Text;
addr_urbn_parm = new SqlParameter("@cmty_id", System.Data.SqlDbType.VarChar);
addr_urbn_parm.Direction = ParameterDirection.Input;
addr_urbn_parm.Value = ds.ToString();
da.SelectCommand.Parameters.Add(addr_urbn_parm);
addr_urbn_conn.Open();
da.Fill(ds);
addr_urbn_conn.Close();
this.txtAddrUrbnCmtyID.DataBind();
Help!!!!!!!
Krisman
|
|
|
|
|
try this
DataSet dSet = new DataSet;
///fill DataSet here
if(dSet.Tables["YourTable"].Rows.Count >0)
TextBox.Text=dSet.Tables["YourTable"].Rows[0]["YouFieldName"].ToString();
|
|
|
|
|
Not quite getting result I thought, but at least there is a result! I'll do some more tinkering.
Thanks!
Krisman
|
|
|
|
|
Or try using a Convert.ToString() around your DataSet result. Somehow ToString sometimes returns the Class name, i.e. DataColumn
|
|
|
|
|
You can't just call DataBind() and expect .NET to solve everything for you.
You need to specify to which property of the textbox you want to bind the data to, and the table and column in the dataset.
Here's an example to bind the data to textbox's text property:
this.txtAddrUrbnCmtyID.DataBindings.Add(new Binding("Text", ds, "tableName.columnName"));
For more information, check the MSDN site for Binding Class[^].
Edbert P.
Sydney, Australia.
|
|
|
|
|
This will only work in a Windows Form, I've learned that much. I'm building WebForms, so I have to come up with different round-about ways to do things. Microsoft has never been known for being user and/or developer friendly.
Krisman
|
|
|
|
|
I doubt that, because I have used data binding in my web project.
Here's an excerpt of the code that I used:
cbApplication.DataSource = dsApplication.Tables(0)
cbApplication.DataTextField = "DirectoryName"
cbApplication.DataValueField = "IDDirectory"
cbApplication.DataBind()
Edbert P.
Sydney, Australia.
|
|
|
|
|
I'll have to try again. But I keep getting errors and our .Net gurus where I work (our network guys) said it's because I'm trying to use a Windows Forms functionality with a Web Form. But I'm also working without a Localhost because of the way .Net was installed on our systems and servers.
Krisman
|
|
|
|
|
I've been looking around the forums for hints on adding to the Windows context menu. I think I've figured it out reading eh Windows Shell programming guide. But I noticed i have install the DOSHere PowerToy some time ago, but I have never seen the DOS Here menu option in the Windows shell menu for directories. Does anyone know if XP no allows Context menu extensions for Directories anymore ?
here is the registry seetings for the DOS Here shel entry that does not show up:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Directory\shell]
@="none"
[HKEY_CLASSES_ROOT\Directory\shell\DosHere]
@="Command &Prompt Here"
[HKEY_CLASSES_ROOT\Directory\shell\DosHere\command]
@="C:\\WINDOWS\\System32\\cmd.exe /k cd \"%1\""
I even tried my own but it didn't work
|
|
|
|
|
|
i know this sounds simple but can someone please tell me how i can draw boxes and circles to the printer
thanks
chad
|
|
|
|
|
Check out the PrintDocument and Graphics classes. Printing is essentially no different from drawing on a windows form, the medium is just different.
|
|
|
|
|
How can you lock a file in .NET? I have a windows application that reads xml files. If two users are trying to read the same file, I want to lock the file so the second user can't read or change the file.
I'm looking for the most bare bones lock and unlock functionality.
Thanks
|
|
|
|
|
The System.IO.FileStream can do this. Read the .NET Framework SDK for more information:
FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None);
XmlTextReader reader = new XmlTextReader(stream);
try
{
}
finally
{
reader.Close();
stream.Close();
} This is a very simplistic example. Read about the FileStream constructor for more information.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|