Is there any way to delete history & cookies of Microsoft Edge browser using VBScript or .net?
Like Internet Explorer, deleting the history form "%AppData%\Local\Microsoft\Windows\History" folder or Rundll32 commands?
Rundll32 commands
Delete Cookies:
rundll32.exe,InetCpl.cpl,ClearMyTracksByProcess 2
Delete History:
rundll32.exe,InetCpl.cpl,ClearMyTracksByProcess 1
Edit:
Found an solution for clearing cookie http://winhelp2002.mvps.org/cookies.htm. Deleting files from following 4 folders will clear cookies without affecting history and cache.
1. \Users\user name\AppData\Local\Packages\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\AC\#!001\MicrosoftEdge\Cookies
2. \Users\user name\AppData\Local\Packages\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\AC\#!002\MicrosoftEdge\Cookies
3. \Users\user name\AppData\Local\Packages\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\AC\#!121\MicrosoftEdge\Cookies
4. \Users\user name\AppData\Local\Packages\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\AC\MicrosoftEdge\Cookies
Still need help to clear history without affecting cookie and cache
This is not Safe But First You need To Close Microsoft Edge browser, Then you should delete All Sub_Folders and Files are in :
"C:\Users\[username]\AppData\Local\Packages\Microsoft.MicrosoftEdge_8wekyb3d8bbwe"
Change [username] with your own Windows Username.
VB Script Code :
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder("C:\Users\[username]\AppData\Local\Packages\Microsoft.MicrosoftEdge_8wekyb3d8bbwe")
for each f in folder.Files
On Error Resume Next
name = f.name
f.Delete True
If Err Then
WScript.Echo "Error deleting:" & Name & " - " & Err.Description
Else
WScript.Echo "Deleted:" & Name
End If
On Error GoTo 0
Next
For Each f In folder.SubFolders
On Error Resume Next
name = f.name
f.Delete True
If Err Then
WScript.Echo "Error deleting:" & Name & " - " & Err.Description
Else
WScript.Echo "Deleted:" & Name
End If
On Error GoTo 0
Next
Note : Run This Source AS ADMIN
Another Way :
Call WshShell.Run("powershell -command Get-AppXPackage -AllUsers -Name Microsoft.MicrosoftEdge | Foreach {Add-AppxPackage -DisableDevelopmentMode -Register “$($_.InstallLocation)\AppXManifest.xml” -Verbose}")
RUN AS ADMIN TOO
Related
Total newbie at C# and Windows command prompt, so please be patient with me.
This is my first time to write code to create an executable designed to alter the registry, as well as, the preferences in Chrome.
A little background first. The engineers at the company that I am contracted to, use an old program called Cadkey, which is used to view files of things that the company has been manufacturing since the 40s.
As many of you probably know, Chrome no longer allows for applets and other type of files to be viewed in the browser for security purposes, but most engineers at this company would rather use Chrome than IE.
As a result, I have been charged with the task of giving them the ability to open the file via an "application link" and some have also referred to this as "custom url protocol" like the following example:
some file
This allows the engineers to click on the file name in the browser, which then opens the file in the program Cadkey.
To accomplish this, I have to register the key within the user's registry, as well as, alter the preference file of Chrome, so that they are not bothered with the little window that alerts them that this file is about to use the Windows command prompt. I had no issue with the later, but my boss wanted the process to be as smooth as possible.
With all of this said, I was able to accomplish this with the following code:
using System;
using System.IO;
using Microsoft.Win32;
using Newtonsoft.Json.Linq;
namespace CadkeyRegAndPrefs
{
class Program
{
static void Main()
{
try
{
RegistryKey hkCurUsr = Registry.CurrentUser.OpenSubKey("Software\\Classes", true);
// Create a subkey named cadkey under HKEY_CURRENT_USER.
RegistryKey cadkey = hkCurUsr.CreateSubKey("cadkey", true);
cadkey.SetValue("", "URL:cadkey Protocol");
cadkey.SetValue("URL Protocol", "");
// Create data for the defltIcn subkey.
RegistryKey cadkeyDefltIcn = cadkey.CreateSubKey("DefaultIcon", true);
cadkeyDefltIcn.SetValue("", "");
cadkeyDefltIcn.SetValue("C:\\CK19\\Ckwin.exe", "-1");
// Create data for the cadkeyShell subkey.
RegistryKey cadkeyShell = cadkey.CreateSubKey("shell", true);
RegistryKey cadkeyShellOpen = cadkeyShell.CreateSubKey("open", true);
// Create data for the cadkeyCommand subkey.
RegistryKey cadkeyCommand = cadkeyShellOpen.CreateSubKey("command", true);
cadkeyCommand.SetValue("", "");
cadkeyCommand.SetValue("", "cmd /V:ON /C \"SET r=%1 & start C:\\CK19\\Ckwin.exe !r:cadkey:=!\"");
// Retrieve path of the current user
string path = System.Environment.ExpandEnvironmentVariables("%userprofile%");
string pathToPrefs = path + "\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Preferences";
// Have to create a JObject of the json file
JObject jsonObj = JObject.Parse(File.ReadAllText(pathToPrefs));
// Determine if the user has a protocol handler set and append cadkey set to false, otherwise, create node and set cadkey to false
var isExlcudedSchemes = jsonObj.SelectToken("protocol_handler.excluded_schemes");
if (isExlcudedSchemes != null)
{
jsonObj["protocol_handler"]["excluded_schemes"]["cadkey"] = false;
} else {
jsonObj.Add(new JProperty("protocol_handler", new JObject(
new JProperty("excluded_schemes", new JObject(
new JProperty("cadkey", new JObject()))))));
jsonObj["protocol_handler"]["excluded_schemes"]["cadkey"] = false;
}
// set the variable output and write the json content to the preferences file for Chrome
string output = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText(pathToPrefs, output);
// Let the end user know that the operation was successful
Console.WriteLine("Cadkey registration installed successfully");
Console.WriteLine("\nPress any key to exit");
Console.ReadKey();
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e.ToString());
}
}
}
}
The engineers have a little bootstrap modal, which gives them the instructions to download the exe, followed by double clicking the exe to install the registry keys and alter the Chrome prefs.
So what's the problem? The code registers the keys to the user's registry, as well as altering the Chrome preferences file, along with informing the user at the end that it was successful.
The problem is that some of the files have a space in the name, which then makes Cadkey prompt the user that the file cannot be found. Mainly because "%20" appears in the place of the space. I guess Cadkey was made at a time when urlencoding was not part of the design.
I have tried to alter the url via the command prompt, as I do with removing the string "cadkey:" from the param being passed to the command prompt:
cmd /V:ON /C \"SET r=%1 & start C:\\CK19\\Ckwin.exe !r:cadkey:=! & !r:%20= !\"
I have tried:
cmd /V:ON /C \"SET r=%1 & start C:\\CK19\\Ckwin.exe !r:cadkey:=! | !r:%20= !\"
I have tried:
cmd /V:ON /C \"SET r=%1 & start C:\\CK19\\Ckwin.exe !r:cadkey:=! & !r:%%20= !\"
I have tried using another var
cmd /V:ON /C \"SET r=%1 & !r:cadkey:=! & SET s=r start C:\\CK19\\Ckwin.exe !s:%20= !\"
While the command is successful in replace the string "cadkey:" - I have yet to replace both strings at the same time. I have tried too many things, but I am a newbie at this, any help would be appreciated.
Thanks in advance
After working with my boss on this last night, we finally found an answer, which is the following:
Change
cadkeyCommand.SetValue("", "cmd /V:ON /C \"SET r=%1 & start C:\\CK19\\Ckwin.exe !r:cadkey:=!\"");
To:
cadkeyCommand.SetValue("", "cmd /V:ON /C \"SET r=%1 & SET s=!r:cadkey:= ! & SET t=!s:%%20= ! & start C:\\CK19\\Ckwin.exe !t!\"");
The result is that the both the string "cadkey:" and the string "%20" are removed, with the string "%20" replaced by a space, which results in the following being passed to cadkey where you see the variable "t"
I am trying to run git-cmd.exe from my code using Process. Below commands when passed to git-cmd.exe runs successfully when the git diff is happening between 2 branches.
git init
git remote add origin "<repo-name>"
git fetch origin <branch1>
git fetch origin <branch2>
git diff --name-only --diff-filter=d <branch1>:<folder1> <branch2>:<folder1>
I need to find the file names which were modified or added in <folder1> only, between the given branches. I am executing these commands by passing them as a string[] to a function.
Public Function RunAndReturnExitCode(ByVal Command As String(), ByVal Directory As String,
Optional ByVal MaximumWaitTime As Integer = -1,
Optional ByRef Output As String = Nothing,
Optional ByRef Errors As String = Nothing) As String
Dim exePath As String = "C:\Program Files (x86)\PortableGit\git-cmd.exe"
Dim si As ProcessStartInfo = New ProcessStartInfo(exePath)
si.RedirectStandardInput = True
si.RedirectStandardOutput = True
si.RedirectStandardError = True
si.UseShellExecute = False
si.WorkingDirectory = Directory
Dim p As Process = Process.Start(si)
With p.StandardInput
.WriteLine("cd /d """ & Directory & """")
Array.ForEach(Command, Sub(c) .WriteLine(c))
.WriteLine("exit")
End With
p.WaitForExit(MaximumWaitTime)
Output = p.StandardOutput.ReadToEnd()
Errors = p.StandardError.ReadToEnd()
Return p.ExitCode.ToString()
End Function
Due to performance issues, we have now started working on tags. So, I am now doing:
git init
git remote add origin "<repo-name>"
git fetch origin refs/tags/[tag1]
git fetch origin refs/tags/[tag2]
git diff --name-only --diff-filter=d [tag1]:[folder1] [tag2]:[folder1]
Here, the diff command fails by:
fatal: Invalid object name '[tag1]'.
I tried running a few commands manually from git-cmd.exe, where I found git checkout refs/tags/[tag1] itself failed by:
error: pathspec '[tag1]' did not match any file(s) known to git.
Does this mean that my local repository does not have any info of [tag1]? If not, then why was there no error while fetching them? Can anyone suggest here, how I can fetch only these 2 tags and do a diff between them?
Tried git diff tag1 tag2, but its failing by :
fatal: ambiguous argument '[tag1]': unknown revision or path not in the working tree.
Please please let me know if any more inputs are required here from me. Also, I can not do a git fetch --tags as it hangs (I suppose, this is not the issue here as fetching the tags separately does not hang). To add, my organization does not permit usage of https://github.com/libgit2/libgit2sharp/.
EDIT:
As suggested by #torek, a git fetch refs/tags/tag1 was a wrong approach. I have now updated it to:
git fetch origin +refs/tags/tag1:refs/tags/tag1 +refs/tags/tag2:refs/tags/tag2
The command works fine on git-cmd.exe and I am able to get the diff. But it hangs when I fire through a process. My SSH repository does not have a pass-phrase, so it is for sure that the RSA Aunthentication isn't failing. Any suggestions here? Am I firing the commands correctly via the process?
This:
git fetch origin refs/tags/[tag1]
is wrong as it obtains the desired commit but does not write any name in your repository. The commit is now available through FETCH_HEAD, but only until the next git fetch. That is:
git fetch origin refs/tags/[tag2]
obtains that desired commit, but overwrites FETCH_HEAD, so that now the only name you have—FETCH_HEAD—refers only to the second desired commit.
To fix this, you could either fetch both and discard their tag names, but now have both hash IDs in FETCH_HEAD (you would have to retrieve them yourself), or you can direct git fetch to create or update your refs/tags/tag1 and refs/tags/tag2 names:
git fetch origin +refs/tags/tag1:refs/tags/tag1 +refs/tags/tag2:refs/tags/tag2
The colon and second name provide the name of the reference to create-or-update in your Git repository. The leading plus sign + here tells git fetch that this particular update should be forced, i.e., it should overwrite any previous tag of the same name.
Of course, git fetch --tags should work. (git pull --tags means run git fetch --tags, then run a second Git command, probably git merge. If you don't want to run any second Git command automatically, don't use git pull.) If this hangs, it may be worth investigating why: all it does is call up the other Git just like any git fetch, but this time also fetch refs/tags/*:refs/tags/*.
I'm trying to Implement The Bell-La Padula Model on local windows accounts in C# , and in this model the user in lower security level can write to files that belong to higher security level without read it !!
I've Added permissions to files like this
file.txt : read [deny] - write [Allow]
Now I'm working on allow user to append text to file.txt without read it .
I used this :
using (FileStream aFile = new FileStream(filename, FileMode.Append, FileAccess.Write))
using (StreamWriter sw = new StreamWriter(aFile))
{
sw.WriteLine(DateTime.Now.ToString() + " Modified BY :" + username + Environment.NewLine);
sw.WriteLine(textBox1.Text);
sw.WriteLine("---------- END User Edition --------------");
}
It worked when I run The program from the Admin account ,but when I tried to run it from Guset account it raise exception : you can't access this file !
I've tried to add read permissions before Start Editing and remove it after finish , but the the file permissions never changed .
Is there any programmatic way that I can implement that , or allow my application to make effect on file when run it within Guest account ?
Took a little time but got it figured out. Had to use procmon to figure it out. Your code is fine. However, you need to setup permissions properly.
For your text file, you need to grant the limited account rights to Write only. Do not check anything under the deny column. Because if you do, the deny access will trump anything else. You also need to grant that account access to Read Attributes and Read Extended Attributes permissions as well.
You can probably accomplish the same thing using icacls or cacls. Here are the manual instructions on how to do it manually. This is based on Windows 10 (Win7 should be similar):
Right click on the file
click on properties.
switch to Security tab.
Click on "Edit" button
Click on "Add..." button
Find the limited user account.
Back in the permissions tab, select the account.
uncheck everything except "Write" checkbox.
Click "OK" to close this dialog box.
Click on "Advanced" button.
Select the account and click "Edit" button.
On the next dialog box, click "Show advanced permissions"
Make sure that the following check boxes are checked.
Read Attributes
Read extended attributes
Create files / write data
Create folders / append data
Write attributes
Write extended attributes
Click OK on all the dialog boxes.
To do this programmatically, you need to allow these:
System.Security.AccessControl.FileSystemRights.AppendData
System.Security.AccessControl.FileSystemRights.CreateFiles
System.Security.AccessControl.FileSystemRights.ReadAttributes
System.Security.AccessControl.FileSystemRights.ReadExtendedAttributes
System.Security.AccessControl.FileSystemRights.WriteAttributes
System.Security.AccessControl.FileSystemRights.WriteExtendedAttributes
Extra info here
Read/Write(Extended)Attributes are necessary for write operations, above will let users to create log files and append text to them without being able to read anything, If you add Delete permission, that will make rolling of the log files possible as well (i'd say most of people will need it as having unlimited size logs without rolling is quite dangerous)
This can be done via any .NET language, PowerShell example (create and write logs files and roll them permissions):
$acl = Get-Acl "C:\logs"
$acl.SetAccessRuleProtection($true, $false) # Remove inherited
$acl.Access | % { $acl.RemoveAccessRule($_) } | Out-Null # Remove existing
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")))
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators", "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")))
$logsRights = [System.Security.AccessControl.FileSystemRights]::AppendData -bor `
[System.Security.AccessControl.FileSystemRights]::CreateFiles -bor `
[System.Security.AccessControl.FileSystemRights]::Delete -bor `
[System.Security.AccessControl.FileSystemRights]::ReadAttributes -bor `
[System.Security.AccessControl.FileSystemRights]::ReadExtendedAttributes -bor `
[System.Security.AccessControl.FileSystemRights]::WriteAttributes -bor `
[System.Security.AccessControl.FileSystemRights]::WriteExtendedAttributes
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("Users", $logsRights, "ContainerInherit, ObjectInherit", "None", "Allow")))
Set-Acl "C:\logs" $acl
Write-Host "logs ACL"
$acl.Access
Depending on your use case you may or may not need to clear existing rules and add SYSTEM/Administrators, but you get the idea
I have a CopyDirectory step in my build template, and I was assuming that if it finds a directory that does not exist, it would throw errors. However, it is only throwing a warning, and the build itself is marked successful.
I've tried to wrap it around a try/catch block, and manually did a 'throw' exception step, but still didn't work. I tried to set the buildStatus to failed, but that didn't work either. Any another way I can achieve this? I don't want the build to be successful if any of the copy directory fails.
EDIT:
Here is the snippet where the copy directory is. I'm looping over a list of servers and copying a bunch of directories.
<ForEach x:TypeArguments="x:String" sap2010:WorkflowViewState.IdRef="ForEach`1_4" Values="[SCCDServers]">
<ActivityAction x:TypeArguments="x:String">
<ActivityAction.Argument>
<DelegateInArgument x:TypeArguments="x:String" Name="server" />
</ActivityAction.Argument>
<Sequence sap2010:WorkflowViewState.IdRef="Sequence_37">
<mtbwa:CopyDirectory Destination="[server]" DisplayName="Copy Code Files" sap2010:WorkflowViewState.IdRef="CopyDirectory_14" Source="[BuildDetail.DropLocation & "\_PublishedWebsites\" & SCWebOutputFolder]" />
<mtbwa:WriteBuildMessage sap2010:WorkflowViewState.IdRef="WriteBuildMessage_16" Importance="[Microsoft.TeamFoundation.Build.Client.BuildMessageImportance.High]" Message="["Code Files copied to " & server]" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces" />
<mtbwa:CopyDirectory Destination="[server]" DisplayName="Copy Config Files" sap2010:WorkflowViewState.IdRef="CopyDirectory_15" Source="[BuildDetail.DropLocation & "\_PublishedWebsites\" & SCConfigSourceFolder & "\" & SCCDServerRole]" />
<mtbwa:WriteBuildMessage sap2010:WorkflowViewState.IdRef="WriteBuildMessage_17" Importance="[Microsoft.TeamFoundation.Build.Client.BuildMessageImportance.High]" Message="["Config Files copied to " & server & Environment.NewLine & "Copied from: " & BuildDetail.DropLocation & "\_PublishedWebsites\" & SCConfigSourceFolder & "\" & SCCDServerRole]" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces" />
<mtbwa:CopyDirectory Destination="[server]" DisplayName="Copy Sitecore Files" sap2010:WorkflowViewState.IdRef="CopyDirectory_16" Source="[BuildDetail.DropLocation & "\_PublishedWebsites\" & SCSitecoreFilesSourceFolder]" />
<mtbwa:WriteBuildMessage sap2010:WorkflowViewState.IdRef="WriteBuildMessage_18" Importance="[Microsoft.TeamFoundation.Build.Client.BuildMessageImportance.High]" Message="["Sitecore Files copied to " & server & Environment.NewLine & "Copied from: " & BuildDetail.DropLocation & "\_PublishedWebsites\" & SCSitecoreFilesSourceFolder]" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces" />
</Sequence>
</ActivityAction>
</ForEach>
CopyDirectory indeed has a bug that only issues a warning when the source directory doesn't exist. It also has problems with long paths (>248 chars).
Possible workarounds:
Use InvokeCommand, running Robocopy.exe (better than xcopy) and checking its resultcode.
If you must use CopyDirectory, check yourself that the source directory exists.
Why dont you make use of the "InvokeProcess" activity then?
Select the activity, open the Variables tab at the bottom.
Add a variable "ResultCode" of type Int32. This variable will contain the exit code from the copy process.
Add the "InvokeProcess" activity to your workflow.
Open the "InvokeProcess" activity and drop a "WriteBuildMessage" activity inside the Handle Standard Output section.
Set the Importance property to Microsoft.TeamFoundation.Build.Client.BuildMessageImportance.High. Set the Message property to stdOutput.
Drop an instance of the WriteBuildError activity to the Handle Error Output section
Set the Message property to errOutput
Now Set "InvokeProcess" properties
FileName: "xcopy"
Agruments: "Source" "Destination" \s \e \y
Result: ResultCode
Check the "ResultCode" value. I use an IF activity and check for the condition "ResultCode <> 0". Within the "THEN" section add a "THROW" activity and add the exception:
"New Exception("Error copying files")
Details here
If copy fails, Set setbuildproperties status to failed in your custom workflow.
<mtbwa1:SetBuildProperties DisplayName=“Set build status failed“ PropertiesToSet=“Status“ Status=“[Microsoft.TeamFoundation.Build.Client.BuildStatus.Failed]“ />
http://msdn.microsoft.com/en-us/library/bb399143(v=vs.100).aspx
For example, I deleted a record on a table on the database and my database is MS Aaccess. Any backup mechanisms that I can refer to? So that when I need a rollback of the database I just restore it quickly from code.
MS Access is the file based database, right? in my understanding, that means, when the connection is closed and the file is not in use, you can copy that file to another location.
Here I assume the application has such privileges on the file system.
Also, I agree with Morten Martner's answer, if the database type is MS SQL Server, then you will definitely need SMO library use.
I'm using the following code to backup SQL server databases:
using System;
using System.Collections.Generic;
using System.Data;
using System.Collections;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using System.Text;
namespace Codeworks.SqlServer.BackupDatabase
{
public class BackupCore
{
public static void Execute( string instance, string database, string outputFile )
{
BackupDeviceItem bdi = new BackupDeviceItem( outputFile, DeviceType.File );
Backup bu = new Backup();
bu.Database = database;
bu.Devices.Add( bdi );
bu.Initialize = true;
// add percent complete and complete event handlers
bu.PercentComplete += new PercentCompleteEventHandler(Backup_PercentComplete);
bu.Complete +=new ServerMessageEventHandler(Backup_Complete);
Server server = new Server( instance );
bu.SqlBackup( server );
}
protected static void Backup_PercentComplete( object sender, PercentCompleteEventArgs e )
{
// Console.WriteLine( e.Percent + "% processed." );
}
protected static void Backup_Complete( object sender, ServerMessageEventArgs e )
{
Console.WriteLine( e.ToString() );
}
}
}
You'll need the management libraries from MS for the correct SQL server version, but those are available for download.
If you're a single user of your database, you just need to close your connection and copy it with the file system.
If there are multiple users, then you should use a different method. If you actually have Access available, there's an undocumented command that will make a backup of the tables a Jet/ACE file:
Application.SaveAsText 6, vbNullString, strTargetMDB
Now, since this can only be done with the database open in the Access UI, it requires automating Access and operating on the CurrentDB. Here's an implementation that runs within Access:
Public Function CreateBackup(strMDBName As String, strBackupPath As String, _
Optional bolCompact As Boolean = False) As Boolean
On Error GoTo errHandler
Dim objAccess As Object
Dim strBackupMDB As String
Dim strCompactMDB As String
If Len(Dir(strBackupPath & "\*.*")) = 0 Then ' alternative: use File System Object for this
MkDir strBackupPath
End If
Set objAccess = New Access.Application
objAccess.Application.OpenCurrentDatabase strMDBName
strBackupMDB = "Backup" & Format(Now(), "YYYYMMDDhhnnss") & ".mdb"
Debug.Print strBackupPath & "\" & strBackupMDB
objAccess.Application.SaveAsText 6, vbNullString, strBackupPath & "\" & strBackupMDB
objAccess.Application.Quit
Set objAccess = Nothing
If bolCompact Then
strCompactMDB = strBackupPath & "\" & "c_" & strBackupMDB
Name strBackupPath & "\" & strBackupMDB As strCompactMDB
DBEngine.CompactDatabase strCompactMDB, strBackupPath & "\" & strBackupMDB
Kill strCompactMDB
End If
CreateBackup = (Len(Dir(strBackupPath & "\" & strBackupMDB)) > 0)
exitRoutine:
If Not (objAccess Is Nothing) Then
On Error Resume Next
objAccess.Application.Quit
On Error GoTo 0
Set objAccess = Nothing
End If
Exit Function
errHandler:
Select Case Err.Number
Case 75 ' Path/File access error -- tried to MkDir a folder that already exists
Resume Next
Case Else
MsgBox Err.Number & ": " & Err.Description, vbExclamation, "Error in CreateBackup()"
Resume exitRoutine
End Select
End Function
To run that from C# you'd have to automate Access, and you likely don't want a dependency on Access.
Since I work in Access exclusively, that's the method I use, so I've never programmed the more complicated methods.
If you have exclusive access to the database, you could use JRO CompactDatabase command to compact to a new filename, but if you have exclusive access, you can also use the file system.
So, basically, you've got choices about how to export the data tables to a backup database. You could use DoCmd.TransferDatabase to copy all the data tables, and then copy the relationships, or you could create an empty template database and append the data from each table in turn to a copy of the template (in an order that won't violate RI, of course).
Neither of those sounds anything but messy to me, and that's why I use the SaveAsText method! But if I wasn't running Access, the other two alternatives would be worth doing.