I currently use pcsc-sharp to read ids from NFC tags. I got this methode to lists all available readers. But this replys me all readers I ever used. There are also old readers listed that aren´t plugged in. Does anyone know how to fix that?
public void SelectDevice()
{
List<string> availableReaders = this.ListReaders();
this.RdrState = new Card.SCARD_READERSTATE();
readername = availableReaders[0].ToString();
this.RdrState.RdrName = readername;
}
public List<string> ListReaders()
{
int ReaderCount = 0;
List<string> AvailableReaderList = new List<string>();
retCode = Card.SCardListReaders(hContext, null, null, ref ReaderCount);
if (retCode != Card.SCARD_S_SUCCESS)
{
MessageBox.Show(Card.GetScardErrMsg(retCode));
}
byte[] ReadersList = new byte[ReaderCount];
retCode = Card.SCardListReaders(hContext, null, ReadersList, ref ReaderCount);
if (retCode != Card.SCARD_S_SUCCESS)
{
MessageBox.Show(Card.GetScardErrMsg(retCode));
}
string rName = "";
int indx = 0;
if (ReaderCount > 0)
{
while (ReadersList[indx] != 0)
{
while (ReadersList[indx] != 0)
{
rName = rName + (char)ReadersList[indx];
indx = indx + 1;
}
AvailableReaderList.Add(rName);
rName = "";
indx = indx + 1;
}
}
return AvailableReaderList;
}
Okay I think I solved the problem. Don´t know if this is the best way, but it works. I also don´t know why the ListReaders()-Method delivers me all readers I ever used, but I found another way to get the reader name of the reader that is currently plugged in.
public void SelectDevice()
{
string[] readerNames = new string[1];
using (var context = new SCardContext())
{
context.Establish(SCardScope.System);
readerNames = context.GetReaders();
}
readername = readerNames[0];
this.RdrState.RdrName = readername;
}
If there´s a better way, or someone knows why I get all readers ever used, please comment.
Related
I want to remove all attachments form a mail in outlook. Don't know, what I'm doing wrong. The code does not cause an exception, but the attachments are still available after removing. This is my code:
This gives me an outlook.application object if it is running or is running outlook, if it's not running:
public static OL.Application GetOutlook(out bool StillRunning)
{
OL.Application OLApp = null;
if (System.Diagnostics.Process.GetProcessesByName("OUTLOOK").Count() > 0)
{
StillRunning = true;
return System.Runtime.InteropServices.Marshal.GetActiveObject("Outlook.Application") as Microsoft.Office.Interop.Outlook.Application;
}
else
{
StillRunning = false;
OLApp = new OL.Application();
OL.NameSpace nameSpace = OLApp.GetNamespace("MAPI");
nameSpace.Logon("", "", System.Reflection.Missing.Value, System.Reflection.Missing.Value);
nameSpace = null;
return OLApp;
}
}
This function returns a mail by its EntryID:
public static OL.MailItem GetMailByEntryId(OL.Application OlApp, string MailItemEntryID)
{
OL.NameSpace olNS = null;
object obj = null;
olNS = OlApp.GetNamespace("MAPI");
if (olNS == null) { throw new System.Exception("ERROR: Unable to get Namespace 'MAPI' in Outlook.Application object!"); }
OL.MailItem MI = null;
obj = olNS.GetItemFromID(MailItemEntryID);
if (obj != null && obj is OL.MailItem) { MI = obj as OL.MailItem; }
if (MI == null) { throw new System.Exception("ERROR: Unable to get mail item by ID " + System.Environment.NewLine + MailItemEntryID); }
return MI;
}
Here, I try to remove the attachments of the mail:
public static void RemoveAttachments(string EntryID)
{
bool StillRunning = false;
OL.Application OLApp = GetOutlook(out StillRunning);
OL.MailItem MI = GetMailByEntryId(OLApp, EntryID);
for(int i = 0; i < MI.Attachments.Count; i++) { MI.Attachments.Remove(i); } //Methode Delete() not available...
MI.Save();
if (!StillRunning) { OLApp.Quit(); OLApp = null; System.GC.Collect(); KillOutlook(); }
}
Thank you all for your help...
All collections in OOM (including MailItem.Attachments) are 1 based, not 0. You are also modifying the collection while looping - use a down loop:
Attachments attachments = MI.Attachments;
for(int i = attachments.Count; i >= 1; i--) { Attachments.Remove(i); }
Ahh, got it - You can make it work that way:
foreach(OL.Attachment Att in MI.Attachments){Att.Delete();}
The documentation notes what identifier is used in iOS/Windows builds, but not Android builds. What identifier does SystemInfo.deviceUniqueIdentifier use on Android?
I don't understand why that is not mentioned in the Doc.
Last time I checked, Unity uses Secure.ANDROID_ID to get the Android ID string then converts that to string. If you do that, you should the the-same value as SystemInfo.deviceUniqueIdentifier. This is what's happening on my device.
Unfortunately, more things are going on in the background.
Unity documented their Unique Identifier Details implementation on their forum.
1. Get DeviceId with context.getSystemService(Context.TElEPHONY_SERVICE).getDeviceId()
2.If #1 fails, get Android ID with context.getContentResolver().getString(Secure.ANDROID_ID);
3.If #2 fails, get the Mac Address.
4.Convert result from #1, #2 or #3(which ever one that was successful) to MD5 Hash.
It's worth reading that forum post since the behavior is a little different on some Unity versions.
Here is a sample code provide by them on what it looks like:
// Hash an input string and return the hash as
// a 32 character hexadecimal string.
static string getMd5Hash(string input)
{
if (input == "")
return "";
MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
sBuilder.Append(data[i].ToString("x2"));
return sBuilder.ToString();
}
static string generateDeviceUniqueIdentifier(bool oldBehavior)
{
string id = "";
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity = jc.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaClass contextClass = new AndroidJavaClass("android.content.Context");
string TELEPHONY_SERVICE = contextClass.GetStatic<string>("TELEPHONY_SERVICE");
AndroidJavaObject telephonyService = activity.Call<AndroidJavaObject>("getSystemService", TELEPHONY_SERVICE);
bool noPermission = false;
try
{
id = telephonyService.Call<string>("getDeviceId");
}
catch (Exception e) {
noPermission = true;
}
if(id == null)
id = "";
// <= 4.5 : If there was a permission problem, we would not read Android ID
// >= 4.6 : If we had permission, we would not read Android ID, even if null or "" was returned
if((noPermission && !oldBehavior) || (!noPermission && id == "" && oldBehavior))
{
AndroidJavaClass settingsSecure = new AndroidJavaClass("android.provider.Settings$Secure");
string ANDROID_ID = settingsSecure.GetStatic<string>("ANDROID_ID");
AndroidJavaObject contentResolver = activity.Call<AndroidJavaObject>("getContentResolver");
id = settingsSecure.CallStatic<string>("getString", contentResolver, ANDROID_ID);
if(id == null)
id = "";
}
if(id == "")
{
string mac = "00000000000000000000000000000000";
try
{
StreamReader reader = new StreamReader("/sys/class/net/wlan0/address");
mac = reader.ReadLine();
reader.Close();
}
catch (Exception e) {}
id = mac.Replace(":", "");
}
return getMd5Hash(id);
}
In my project i want list out all files under a specific file path.Do to some user permission issue am using master file table to access all files.
Using this thread I can able to read all files under a specific file location
This one will list the file name and parent FRN,is there any way to list the file attributes also????
I want to show these details also.
Created Date
Modified Data
File Size
USN_RECORD contains these details.
You'd probably be better off using something more high-level to enumerate the contents of a path (as suggested by #HarryJohnston), but if you're determined to go down the route you've chosen, then...
Using the FileReferenceNumber you got from your USN call, you can call OpenFileByID (specifying a 0 for the dwDesiredAccess parameter - no read, no write), and you can then subsequently call GetFileInformationByHandle to get the details you need.
You don't need read or write permissions on the file to call GetFileInformationByHandle. The file attributes you're getting from the USN call and/or the GetFileInformationByHandle call can be cast to a .Net System.IO.FileAttributes.
public IEnumerable<FileDetails> EnumerateFiles(string szDriveLetter)
{
List<FileDetails> fdList = new List<FileDetails>();
try
{
var usnRecord = default(USN_RECORD);
var mft = default(MFT_ENUM_DATA);
var dwRetBytes = 0;
int cb;
var dicFrnLookup = new Dictionary<long, FSNode>();
bool bIsFile;
// This shouldn't be called more than once.
if (m_Buffer.ToInt32() != 0)
{
throw new Exception("invalid buffer");
}
// Assign buffer size
m_BufferSize = 65536;
//64KB
// Allocate a buffer to use for reading records.
m_Buffer = Marshal.AllocHGlobal(m_BufferSize);
// correct path
szDriveLetter = szDriveLetter.TrimEnd('\\');
// Open the volume handle
m_hCJ = OpenVolume(szDriveLetter);
uint iny = NativeMethods.GetLastError();
// Check if the volume handle is valid.
if (m_hCJ == INVALID_HANDLE_VALUE)
{
throw new Exception("Couldn't open handle to the volume.");
}
mft.StartFileReferenceNumber = 0;
mft.LowUsn = 0;
mft.HighUsn = long.MaxValue;
do
{
if (DeviceIoControl(m_hCJ, FSCTL_ENUM_USN_DATA, ref mft, Marshal.SizeOf(mft), m_Buffer, m_BufferSize, ref dwRetBytes, IntPtr.Zero))
{
cb = dwRetBytes;
// Pointer to the first record
IntPtr pUsnRecord = new IntPtr(m_Buffer.ToInt32() + 8);
while ((dwRetBytes > 8))
{
// Copy pointer to USN_RECORD structure.
usnRecord = (USN_RECORD)Marshal.PtrToStructure(pUsnRecord, usnRecord.GetType());
// The filename within the USN_RECORD.
string fileName = Marshal.PtrToStringUni(new IntPtr(pUsnRecord.ToInt32() + usnRecord.FileNameOffset), usnRecord.FileNameLength / 2);
bIsFile = !usnRecord.FileAttribute.HasFlag(FileAttributes.Directory);
dicFrnLookup.Add(usnRecord.FileReferenceNumber, new FSNode(usnRecord.ParentFileReferenceNumber, fileName, bIsFile));
// Pointer to the next record in the buffer.
pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usnRecord.RecordLength);
dwRetBytes -= usnRecord.RecordLength;
}
// The first 8 bytes is always the start of the next USN.
mft.StartFileReferenceNumber = Marshal.ReadInt64(m_Buffer, 0);
}
else
{
break; // TODO: might not be correct. Was : Exit Do
}
} while (!(cb <= 8));
// Resolve all paths for Files
foreach (FSNode oFSNode in dicFrnLookup.Values.Where(o => o.IsFile))
{
FileDetails fd = new FileDetails();
string sFullPath = oFSNode.FileName;
FSNode oParentFSNode = oFSNode;
while (dicFrnLookup.TryGetValue(oParentFSNode.ParentFRN, out oParentFSNode))
{
sFullPath = string.Concat(oParentFSNode.FileName, "\\", sFullPath);
}
sFullPath = string.Concat(szDriveLetter, "\\", sFullPath);
//File Attribute details
WIN32_FILE_ATTRIBUTE_DATA data;
if (NativeMethods.GetFileAttributesEx(#sFullPath, GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, out data))
{
fd.FileSize = Convert.ToDouble(data.fileSizeLow);
}
long highBits = data.creationTime.dwHighDateTime;
highBits = highBits << 32;
DateTime createdDate = DateTime.FromFileTimeUtc(highBits + (uint)data.creationTime.dwLowDateTime);
fd.CreatedDate = createdDate.ToString(CultureInfo.CurrentCulture);
fd.CreatedYear = createdDate.Year;
fd.FileType = data.filetype;
long highBitsModified = data.lastWriteTime.dwHighDateTime;
highBitsModified = highBitsModified << 32;
DateTime modifiedDate = DateTime.FromFileTimeUtc(highBitsModified + (uint)data.creationTime.dwLowDateTime);
fd.ModifiedYear = modifiedDate.Year;
fd.ModifiedDate = modifiedDate.ToString(CultureInfo.CurrentCulture);
fd.FilePath = sFullPath;
fd.MachineName = SystemInformation.ComputerName;
List<string> names = sFullPath.Split('.').ToList();
fd.FileType = "." + names.LastOrDefault();
List<string> folders = sFullPath.Split('\\').ToList();
//fd.FileName = folders.LastOrDefault();
fd.FileName = oFSNode.FileName;
fdList.Add(fd);
yield return fd;
}
}
finally
{
//// cleanup
Cleanup();
}
}
public class NativeMethods
{
[DllImport("KERNEL32.dll", CharSet = CharSet.None)]
public static extern bool GetFileAttributesEx(string path, GET_FILEEX_INFO_LEVELS level, out WIN32_FILE_ATTRIBUTE_DATA data);
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
}
I've made a program and I want to save the data. Saving is working, but "Loading" doesn't work.
public void Save(StreamWriter sw)
{
for (int i = 0; i < buecher.Count; i++)
{
Buch b = (Buch)buecher[i];
if (i == 0)
sw.WriteLine("ISDN ; Autor ; Titel");
sw.WriteLine(b.ISDN + ";" + b.Autor + ";" + b.Titel);
}
}
public void Load(StreamReader sr)
{
int isd;
string aut;
string tit;
while (sr.ReadLine() != "")
{
string[] teile = sr.ReadLine().Split(';');
try
{
isd = Convert.ToInt32(teile[0]);
aut = teile[1];
tit = teile[2];
}
catch
{
throw new Exception("umwandlung fehlgeschlagen");
}
Buch b = new Buch(isd, aut, tit);
buecher.Add(b);
}
}
If I'm doing that with an break after buecher.Add(b); than its everything fine but it obviously shows me only 1 book... if I'm not using the break he gives me an error "nullreference.."
Would be awesome if someone could help me
best regards
Ramon
The problem is that you are reading two lines for each iteration in the loop (and throwing away the first one). If there are an odd number of lines in the file, the second call to Read will return null.
Read the line into a variable in the condition, and use that variable in the loop:
public void Load(StreamReader sr) {
int isd;
string aut;
string tit;
// skip header
sr.ReadLine();
string line;
while ((line = sr.ReadLine()) != null) {
if (line.Length > 0) {
string[] teile = line.Split(';');
try {
isd = Convert.ToInt32(teile[0]);
aut = teile[1];
tit = teile[2];
} catch {
throw new Exception("umwandlung fehlgeschlagen");
}
Buch b = new Buch(isd, aut, tit);
buecher.Add(b);
}
}
}
You are calling sr.ReadLine() twice for every line, once in the while() and once right after. You are hitting the end of the file, which returns a null.
Different approach to this but I suggest it because it's simpler;
Load(string filepath)
{
try
{
List<Buch> buches = File.ReadAllLines(filepath)
.Select(x => new Buch(int.Parse(x.Split(';')[0]), x.Split(';')[1], x.Split(';')[2]));
{
catch
{
throw new Exception("umwandlung fehlgeschlagen");
}
}
You could do it in more lines if you find it to be more readable but I've come to prefer File.ReadAllText and File.ReadAllLines to StreamReader approach of reading files.
Instead of using the LINQ statement you could also do;
Load(string filepath)
{
try
{
string[] lines = File.ReadAllLines(filepath);
foreach (string line in lines)
{
string[] tokens = line.Split(';');
if (tokens.Length != 3)
// error
int isd;
if (!int.TryParse(tokens[0], out isd))
//error, wasn't an int
buetcher.Add(new Buch(isd, tokens[1], tokens[2]);
}
{
catch
{
throw new Exception("umwandlung fehlgeschlagen");
}
}
Is it possible in C# (4.0) to get the list of installed Com+ applications on the same box and then retrieve the status (Running/Shut down) of each of them?
I can find methods to start/stop, but not retrieve status.
I think the COM+ Administrative components only lets you query the "static" configuration properties (e.g. Identity, IsEnabled) and doesn't let you query the dynamic properties of COM+ (e.g. PID).
The only way I found to do what you want is using the COMSVCSLib (COM+ Services Type Library).
UPDATE: Based on #Vagaus's comment, we can use either COM+ Administrative components or COM+ Services Type Library!
With quite a bit of help from the article Comonitor - A COM+ Monitor. I've cobbled together some code that uses COM+ Services Type Library:
public static bool IsComPlusApplicationRunning(string appName)
{
int appDataSize = Marshal.SizeOf(typeof(COMSVCSLib.appData));
Type appDataType = typeof(COMSVCSLib.appData);
uint appCount;
IntPtr appDataPtr = IntPtr.Zero;
GCHandle gh = GCHandle.Alloc(appDataPtr, GCHandleType.Pinned);
IntPtr addressOfAppDataPtr = gh.AddrOfPinnedObject();
COMSVCSLib.IGetAppData getAppData = null;
COMSVCSLib.TrackerServer tracker = null;
try
{
tracker = new COMSVCSLib.TrackerServerClass();
getAppData = (COMSVCSLib.IGetAppData)tracker;
getAppData.GetApps(out appCount, addressOfAppDataPtr);
appDataPtr = new IntPtr(Marshal.ReadInt32(addressOfAppDataPtr));
for (int appIndex = 0; appIndex < appCount; appIndex++)
{
COMSVCSLib.appData appData = (COMSVCSLib.appData)Marshal.PtrToStructure(
new IntPtr(appDataPtr.ToInt32() + (appIndex * appDataSize)),
appDataType);
string currentAppName = GetPackageNameByPID(appData.m_dwAppProcessId);
if (string.Compare(currentAppName, appName, StringComparison.OrdinalIgnoreCase) == 0)
{
Console.WriteLine("Application " + appName + " is running with PID " + appData.m_dwAppProcessId);
return true;
}
}
}
finally
{
Marshal.FreeCoTaskMem(appDataPtr);
if (tracker != null)
{
Marshal.ReleaseComObject(tracker);
}
gh.Free();
}
return false;
}
private static string GetPackageNameByPID(uint PID)
{
COMSVCSLib.MtsGrp grpObj = new COMSVCSLib.MtsGrpClass();
try
{
object obj = null;
COMSVCSLib.COMEvents eventObj = null;
for (int i = 0; i < grpObj.Count; i++)
{
try
{
grpObj.Item(i, out obj);
eventObj = (COMSVCSLib.COMEvents)obj;
if (eventObj.GetProcessID() == PID)
{
return eventObj.PackageName;
}
}
finally
{
if (obj != null)
{
Marshal.ReleaseComObject(obj);
}
}
}
}
finally
{
if (grpObj != null)
{
Marshal.ReleaseComObject(grpObj);
}
}
return null;
}
But we can also use the COM+ Administrative components (which seems simpler) to do the same thing:
public static bool IsComPlusApplicationRunning(string appName)
{
COMAdmin.COMAdminCatalog catalog = new COMAdmin.COMAdminCatalogClass();
COMAdmin.ICatalogCollection appCollection = (COMAdmin.ICatalogCollection)catalog.GetCollection("Applications");
appCollection.Populate();
Dictionary<string, string> apps = new Dictionary<string, string>();
COMAdmin.ICatalogObject catalogObject = null;
// Get the names of the applications with their ID and store for later
for (int i = 0; i < appCollection.Count; i++)
{
catalogObject = (COMAdmin.ICatalogObject)appCollection.get_Item(i);
apps.Add(catalogObject.get_Value("ID").ToString(), catalogObject.Name.ToString());
}
appCollection = (COMAdmin.ICatalogCollection)catalog.GetCollection("ApplicationInstances");
appCollection.Populate();
for (int i = 0; i < appCollection.Count; i++)
{
catalogObject = (COMAdmin.ICatalogObject)appCollection.get_Item(i);
if (string.Compare(appName, apps[catalogObject.get_Value("Application").ToString()], StringComparison.OrdinalIgnoreCase) == 0)
{
Console.WriteLine(appName + " is running with PID: " + catalogObject.get_Value("ProcessID").ToString());
return true;
}
}
return false;
}
Have you checked the COM+ administration components? I'd bet that you can find this information using these interfaces.
Best