Can't create Access Database with ADOX - c#

I have a really strange problem with ADOX Interop.
I have this code:
try
{
if (File.Exists(path))
File.Delete(path);
var cat = new CatalogClass();
cat.Create("Provider=Microsoft.Jet.OLEDB.4.0; Data Source = d:\\Test.mdb; Jet OLEDB:Engine Type=5");
Marshal.ReleaseComObject(cat);
cat = null;
GC.Collect();
}
catch (FileNotFoundException e)
{
throw new FileNotFoundException("El archivo no se encuentra", e);
}
catch (COMException e)
{
throw new COMException(connStr + e.Message);
}
catch (Exception e)
{
throw new Exception(connStr, e);
}
The code is failing in the cat.Create() line. What is really weird is that on my local developer machine it works fine, but in the production server doesn't... It isn't a write permissions problem, because i have tried to generate a random file before the problem line and worked perfectly.
The COMException message is only "Not specified Error" HResult: -2147467259
The Server OS is Windows 2008 32bits. I think is a server configuration issue, but can you give me some light? I don't know what else I can do...

If you deploy your application on a 64 bit machine your code couldn't use ADOX via JET.OleDB.4.0
If this is the case, then, a fast solution could be to change your target architecture to x86.
Otherwise you could try to download and install on the target machine the 64bit version of Microsoft Access Database Engine drivers, but I don't know if they support ADOX. You will also need to change your connection string

See whether you can use ADOX Catalog outside your c# code. If you have Access installed, try with Access VBA as Steve suggested. Without Office installed, try with VBScript.
This one works on my 32 bit Windows 7. On 64 bit Windows 7, it fails with an error about "Class not registered". I realize that is not your situation, since you said your server is 32 bit (in reply to an answer which has since been deleted). However my hope is the script will either succeed or give you a more informative error message than you got from the c# error condition.
'Const cPath = "C:\Users\hans\Documents\Test.mdb"
Const cPath = "d:\Test.mdb"
Dim objCat
Dim strConnect
strConnect = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & cPath & ";Jet OLEDB:Engine Type=5"
WScript.Echo strConnect
Set objCat = CreateObject("ADOX.Catalog")
objCat.Create strConnect
Set objCat = Nothing
I named that file AdoxCreateDb.vbs and ran it with cscript from a command prompt window.
cscript AdoxCreateDb.vbs

Related

SharpSvn.SvnException: sqlite[S8]: attempt to write a readonly database

I got following error when I do `
svnclient.CleanUp(WorkDirPath);`
SharpSvn.SvnException: sqlite[S8]: attempt to write a readonly database
---> SharpSvn.SvnException: Additional errors:
---> SharpSvn.SvnException: sqlite[S8]: attempt to write a readonly database
Update
I have visual studio application and from this application i need upload/download any file to SVN server and this feature can access by end user. so for this i installed VisualSVN Server Manager Version: 4.3.3 on windows server. in my application i imported nuget for this SharpSvn.1.8-x64 to atchive this task (I am new in subversion and client).
Updated : I updated sharpSVN to 1.14001.156 thanks for it. but still my problem is not solved. i still get following error when try to add file "Failed to lock working copy" and then I tried Clean Up Command got "sqlite[S8]: attempt to write a readonly database" error. Is Visual SVN Server Version: 4.3.3 ok with SharpSVN 1.14 ?
following is my code written in C#
svnclient.Authentication.DefaultCredentials = new NetworkCredential(_svnuser, _svnpwd);
CleanCommand(svnclient,_userworkdir);
public bool AddFile(string path, SvnClient svnclient)
{
try
{
return svnclient.Add(path);
}
catch (Exception ex)
{
Log.Error(String.Format(String.Format("Exception in function AddFile := {0} FilePath :- {1}", ex.Message.ToString(), path)));
return false;
}
}
public bool CleanCommand(SvnClient svnclient, String workingdir)
{
bool res = false;
try
{
res = svnclient.CleanUp(workingdir);
}
catch (Exception ex)
{
Log.Error(String.Format(String.Format("Exception in function CleanCommand := {0}, workingdir :- {1}", ex.Message.ToString(), workingdir)));
res = false;
}
return res;
}
Note that SharpSVN 1.8 is outdated. If you use Subversion client based on SharpSVN (AnkhSVN?), it makes sense to update it or to switch to an up-to-date native Subversion 1.14.x client.
As an immediate solution, you can check out a new working copy and continue you work with it. If you have uncommitted changes in the working copy, you can copy them over into a new working copy (don't copy hidden .svn directory though).
I think that something prevents you from opening or writing the contents of the .svn metadata directory. This could be due to insufficient permissions or another program that locks your working copy:
Check NTFS permissions to the .svn directory in the root of your working copy and the .svn/wc.db file in particular (e.g., C:\Users\MyUser\MyVsProject\.svn\wc.db). You should double-check that your user account has permissions to write to C:\Users\MyUser\MyVsProject\ directory and all its contents.
Check if other SVN clients or programs work concurrently with your client and lock the working copy.

Issues with using Managed WiFi (NativeWiFi API)

I am trying to create and connect to a WLAN profile using Native WiFi (https://managedwifi.codeplex.com/). I am able to view all the Network BSS List and their parameters. However, when I am trying to create/overwrite a WLAN profile, I get the below mentioned error message (Error#1):
An unhandled exception of type 'System.ComponentModel.Win32Exception' occurred in ManagedWifi.dll.
Additional information: The network connection profile is corrupted
However, when I created a profile normally from "Network and Sharing Center" of the Windows 7 control panel and then tried to connect using the ManagedWiFi, I get another error message(Error#2):
An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll
Additional information: Type 'NativeWifi.Wlan+WlanReasonCode' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
I noticed that this error occurs even if I try to connect/disconnect to a WLAN profile from the "Network and Sharing Center", with the windows application running in the background.
Here is the sample code that I am using:
Dim profileName As String = GlobalVariables.ssidname ' Provides the selected SSID name from the Network BSS List
Dim hexval As String = StringToHex(GlobalVariables.ssidname) ' Function to get the hexadecimal value for a provided string
Dim key As String = TextBox1.Text ' Security key from the textbook provided
Dim profileXml As String = String.Format("<?xml version=""1.0""?><WLANProfile xmlns=""http://www.microsoft.com/networking/WLAN/profile/v1""><name>{0}</name><SSIDConfig><SSID><hex>{1}</hex><name>{0}</name></SSID></SSIDConfig><connectionType>ESS</connectionType><MSM><security><authEncryption><authentication>open</authentication><encryption>WEP</encryption><useOneX>false</useOneX></authEncryption><sharedKey><keyType>networkKey</keyType><protected>false</protected><keyMaterial>{2}</keyMaterial></sharedKey><keyIndex>0</keyIndex></security></MSM></WLANProfile>", 'GlobalVariables.ssidname, hexval, TextBox1.Text)
wlanIface.SetProfile(Wlan.WlanProfileFlags.AllUser, profileXml, True) 'Error#1 occurs here
wlanIface.Connect(Wlan.WlanConnectionMode.Profile, Wlan.Dot11BssType.Any, profileName) 'Error#2 occurs here
From the forum "Type Native Wifi.Wlan + WlanReasonCode cannot be marshaled error", the issue (Error#2) seems to be within the WlanAPI.cs, where there is a line of code that checks for the size of the return code. This is the line:
int expectedSize = Marshal.SizeOf(typeof(Wlan.WlanReasonCode));
if (notifyData.dataSize >= expectedSize)
{
Wlan.WlanReasonCode reasonCode = (Wlan.WlanReasonCode)Marshal.ReadInt32(notifyData.dataPtr);
if (wlanIface != null)
wlanIface.OnWlanReason(notifyData, reasonCode);
}
Changing the above code to the below seems to fix the issue.
//int expectedSize = Marshal.SizeOf(typeof(Wlan.WlanReasonCode));
if (notifyData.dataSize >= 0)
{
Wlan.WlanReasonCode reasonCode = (Wlan.WlanReasonCode)Marshal.ReadInt32(notifyData.dataPtr);
if (wlanIface != null)
wlanIface.OnWlanReason(notifyData, reasonCode);
}
However, I am not sure on how to add this fix to my solution. I installed the ManagedWiFi from the NuGet Package Manager. Hence, not sure how to change the WlanApi.cs file. Any help regarding the above mentioned two issues are much appreciated.
The issue (Error#1) is now resolved. The profilexml file format was different for me. Here is the profilexml after I changed it.
Dim profileXml As String = String.Format("<?xml version=""1.0""?><WLANProfile xmlns=""http://www.microsoft.com/networking/WLAN/profile/v1""><name>{0}</name><SSIDConfig><SSID><hex>{1}</hex><name>{0}</name></SSID></SSIDConfig><connectionType>ESS</connectionType><connectionMode>auto</connectionMode><MSM><security><authEncryption><authentication>WPA2PSK</authentication><encryption>AES</encryption><useOneX>false</useOneX></authEncryption><sharedKey><keyType>passPhrase</keyType><protected>false</protected><keyMaterial>{2}</keyMaterial></sharedKey></security></MSM></WLANProfile>", GlobalVariables.ssidname, hexval, TextBox1.Text)
Also the second issue (Error#2) was resolved when I uninstalled ManagedWiFi package from my solution and added the whole ManagedWiFi project to the solution. Then I made the change in WlanApi.cs as mentioned in SimpleWiFi Or Type Native Wifi.Wlan + WlanReasonCode cannot be marshaled error.
I had a simpler task (read the SSID of the connected network), which was throwing the same error.
I solved it by switching to using SimpleWiFi entirely and ignore the ManagedWifi package.
Glancing at the source code, it looks like SW is a fixed reimplementation of some of the functionality in MW.

SaveFileDialog.ShowDialog() thrown FileNotFound exception

The following code works fine on Windows 7 (32-bit), but when ported to 64-bit, I get an exception stating "File Not Found". I have built the project in 64-bit configuration but the issue still persists.
The issue occurs if the machine does not have Office installed.
The code is as follows:
try
{
SaveFileDialog fileDialog = new SaveFileDialog();
fileDialog.InitialDirectory = path;
// set the default extension as mdb.
fileDialog.DefaultExt = ".mdb";
// allow the user to select the file type as CSV, XML or MDB.
fileDialog.Filter = "CSV (*.csv)|*.csv|XML (*.xml)|*.xml|MDB (*.mdb)|*.mdb";
fileDialog.RestoreDirectory = true;
if (DialogResult.OK == fileDialog.ShowDialog()) // exception occured
{
this.fileNameTextBox.Text = fileDialog.FileName;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
The question here is what's the value of "path". x86 and x64 machines may have different folder configurations, e.g. Program Files (x86) is one of them. You may start with Environment.SpecialFolders enum, those paths should be valid.

Get my application to be allowed access through firewall using c#

i am trying to get my application to be allowed through firewall, as I have to do ftp in active and passive mode is not an option as servers are not configured for that. so i tried the below code which compiles fine, I exexcute it using:
MyApp.Classes.INetFwMgr mgr = new MyApp.Classes.INetFwMgr();
mgr.AuthorizeApplication(Application.ProductName, Application.StartupPath,
NET_FW_SCOPE_.NET_FW_SCOPE_ALL,
NET_FW_IP_VERSION_.NET_FW_IP_VERSION_ANY);
And the class which does the job:
private const string CLSID_FIREWALL_MANAGER =
"{304CE942-6E39-40D8-943A-B913C40C9CD4}";
private static NetFwTypeLib.INetFwMgr GetFirewallManager()
{
Type objectType = Type.GetTypeFromCLSID(
new Guid(CLSID_FIREWALL_MANAGER));
return Activator.CreateInstance(objectType)
as NetFwTypeLib.INetFwMgr;
}
private const string PROGID_AUTHORIZED_APPLICATION =
"HNetCfg.FwAuthorizedApplication";
public bool AuthorizeApplication(string title, string applicationPath,
NET_FW_SCOPE_ scope, NET_FW_IP_VERSION_ ipVersion)
{
// Create the type from prog id
Type type = Type.GetTypeFromProgID(PROGID_AUTHORIZED_APPLICATION);
INetFwAuthorizedApplication auth = Activator.CreateInstance(type)
as INetFwAuthorizedApplication;
auth.Name = title;
auth.ProcessImageFileName = applicationPath; //Getting Access Denied Exception Here
auth.Scope = scope;
auth.IpVersion = ipVersion;
auth.Enabled = true;
NetFwTypeLib.INetFwMgr manager = GetFirewallManager();
try
{
manager.LocalPolicy.CurrentProfile.AuthorizedApplications.Add(auth);
}
catch (Exception ex)
{
return false;
}
return true;
}
using above code, but i get Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) c# exception on line
auth.ProcessImageFileName = applicationPath;
any ideas what to do ?
Edit1: How would i run this as an admin using code?
Edit2: I also tried Putting <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> in manifest did not make a difference
P.S.This programs execution context can be Win 7, vista, xp
Firewall management is a system level security feature and has to be done outside of user mode application code. Configuration must be done by an administrator.
It is bad practice to write the code that you wrote and assume that your application will be run as administrator. Even if it is run by an administrator, you now have an application that "does FTP stuff" and "does firewall stuff". No application has ever been written like this.
You can write code that interacts with the system firewall, and that code must be run with elevated permissions. Typically such "helper applications" are never even created however as Windows (and every other OS) has all the necessary management tools shipped with the OS (i.e. wf.msc).
i have observed that if i change the order of ftp download statements to following windows dialog appears asking that do you want to allow this program access through firewall; if i click allow access the code works perfectly.
requestDownload = (FtpWebRequest)WebRequest.Create(uri);
requestDownload.UsePassive = false;
requestDownload.KeepAlive = false;
requestDownload.UseBinary = true;
requestDownload.Method = WebRequestMethods.Ftp.DownloadFile;
requestDownload.Credentials = new NetworkCredential(ftpInfoDownload[3], ftpInfoDownload[4]);
responseDownload = (FtpWebResponse)requestDownload.GetResponse();
Stream ftpStream = responseDownload.GetResponseStream();
Try opening the FTP ports in the firewall -- ports 20 and 21 -- and see if that solves your issue.
For running as a different user:
Run Code as a different user (C#)
As for getting through the firewall, have you talked to the person/group responsible for the firewall security? They may have some rules in place that you could use.

What is the Fastest way to read event log on remote machine?

I am working on an application which reads eventlogs(Application) from remote machines. I am making use of EventLog class in .net and then iterating on the Log entries but this is very slow. In some cases, some machines have 40000+ log entries and it takes hours to iterate through the entries.
what is the best way to accomplish this task? Are there any other classes in .net which are faster or in any other technology?
Man, I feel your pain. We had the exact same issue in our app.
Your solution has a branch depending on what server version you're running on and what server version your "target" machine is running on.
If you're both on Vista or Windows Server 2008, you're in luck. You should look at System.Diagnostics.Eventing.Reader.EventLogQuery and System.Diagnostics.Eventing.Reader.EventLogReader. These are new in .net 3.5.
Basically, you can build a query in XML and ship it over to run on the remote computer. Maybe you're just searching for events of a specific type, or maybe just new events from a specific point in time. The search runs on the remote machine, and then you just get back the matching events. The new classes are much faster than the old .net 2.0 way, but again, they are only supported on Vista or Windows Server 2008.
For our app when the target is NOT on Vista/Win2008, we downloaded the raw .evt file from the remote system, and then parsed the file using its binary format. There are several sources of data about the event log format for .evt files (pre-Vista), including link text and an article I recall on codeproject.com that had some c# code.
Vista and Windows Server 2008 machines use a new .evtx format that is a new format, so you can't use the same binary parsing approach across all versions. But the new EventLogQuery and EventLogReader classes are so fast that you won't have to. It's now perfectly speedy to just use the built-in classes.
Event Log Reader is horribly slow... too slow. WTF Microsoft?
Use LogParser 2.2 - Search for C# and LogParser on the Internet (or you can use the log parser commands from the command line). I don't want to duplicate the work already contributed by others.
I pull the log from the remote system by having the log exported as an EVTX file. I then copy the file from the remote system. This process is really quick - even with a network that spans the planet (I had issues with having the log exported to a network resource). Once you have it local, you can do your searches and processing.
There are multiple reasons for having the EVTX - I won't get into the reasons why we do this.
The following is a working example of the code to save a copy of the log as an EVTX:
(Notes: "device" is the network host name or IP. "LogName" is the name of the log desired: "System", "Security", or "Application". outputPathOnRemoteSystem is the path on the remote computer, such as "c:\temp\%hostname%.%LogName%.%YYYYMMDD_HH.MM%.evtx".)
static public bool DumpLog(string device, string LogName, string outputPathOnRemoteSystem, out string errMessage)
{
bool wasExported = false;
string errorMessage = "";
try
{
System.Diagnostics.Eventing.Reader.EventLogSession els = new System.Diagnostics.Eventing.Reader.EventLogSession(device);
els.ExportLogAndMessages(LogName, PathType.LogName, "*", outputPathOnRemoteSystem);
wasExported = true;
}
catch (UnauthorizedAccessException e)
{
errorMessage = "Unauthorized - Access Denied: " + e.Message;
}
catch (EventLogNotFoundException e)
{
errorMessage = "Event Log Not Found: " + e.Message;
}
catch (EventLogException e)
{
errorMessage = "Export Failed: " + e.Message + ", Log: " + LogName + ", Device: " + device;
}
errMessage = errorMessage;
return wasExported;
}
A good Explanation/Example can be found on MSDN.
EventLogSession session = new EventLogSession(Environment.MachineName);
// [System/Level=2] filters out the errors
// Where "Log" is the log you want to get data from.
EventLogQuery query = new EventLogQuery("Log", PathType.LogName, "*[System/Level=2]");
EventLogReader reader = new EventLogReader(query);
for (EventRecord eventInstance = reader.ReadEvent();
null != eventInstance;
eventInstance = reader.ReadEvent())
{
// Output or save your event data here.
}
When waiting 5-20 minutes with the old code this one does it in less than 10 seconds.
Maybe WMI can help you:
WMI with C#
Have you tried using the remoting features in powershell 2.0? They allow you to execute cmdlets (like ones to read event logs) on remote machines and return the results (as objects, of course) to the calling session.
You could place a Program at those machines that save the log to file and sends it to your webapplication i think that would be alot faster as you can do the looping local but im not sure how to do it so i cant ive you any code :(
I recently did such thing via WCF callback interface however my clients interacted with the server through WCF and adding a WCF Callback was easy in my project, full code with examples is available here
Just had the same issue and want to share my solution. It makes a search through application, system and security eventlogs from 260 seconds (using EventLog) about a 100 times faster (using EventLogQuery).
And this in a way where it is possible to check if the event message contains a pattern or any other check without the requirement of FormatDescription().
My trick is to use the same mechanism as PowerShells Get-WinEvent does and then pass it through the result check.
Here is my code to find all events within last 4 days where the event message contains a filter pattern.
string[] eventLogSources = {"Application", "System", "Security"};
var messagePattern = "*Your Message Search Pattern*";
var timeStamp = DateTime.Now.AddDays(-4);
var matchingEvents = new List<EventRecord>();
foreach (var eventLogSource in eventLogSources)
{
var i = 0;
var query = string.Format("*[System[TimeCreated[#SystemTime >= '{0}']]]",
timeStamp.ToUniversalTime().ToString("o"));
var elq = new EventLogQuery(eventLogSource, PathType.LogName, query);
var elr = new EventLogReader(elq);
EventRecord entryEventRecord;
while ((entryEventRecord = elr.ReadEvent()) != null)
{
if ((entryEventRecord.Properties)
.FirstOrDefault(x => (x.Value.ToString()).Contains(messagePattern)) != null)
{
matchingEvents.Add(entryEventRecord);
i++;
}
}
}
Maybe that the remote computers could do a little bit of computing. So this way your server would only deal with relevant information. It would be a kind of cluster using the remote computer to do some light filtering and the server would the the analysis part.

Categories

Resources