前言
项目由于以前是把数据库和主程序放在一台电脑上,所以出于安全目的现在要把数据库和程序分离,把数据库放到内网里,不公布到外网上.这样一般的数据库操作都没问题,就是备份和还原数据库需要实现远程备份和还原.
我实现的是用的数据库的xpcmd命令,在主程序机器上临时开一个局域网共享文件夹,然后在远程数据库上开启xpcmd来执行net use命令连接上共享,然后就可以按本在本机一样还原备份.
简单的思路就是这样的,缺点就是很多数据库会干掉xpcmd用的那个dll,所以不是十全十美吧.
实现
下面就看下具体的实现过程:
1:在本机开一个共享文件夹
//
开启本机共享
Process p = new Process();
p.StartInfo.FileName = " cmd.exe " ;
p.StartInfo.UseShellExecute = false ;
p.StartInfo.RedirectStandardInput = true ;
p.StartInfo.RedirectStandardOutput = true ;
p.StartInfo.RedirectStandardError = true ;
p.StartInfo.CreateNoWindow = true ;
p.StartInfo.Arguments = " /c net share 共享的名称(例如test)=要开启共享的文件夹(例如c:\\testfolder) " ;
p.Start();
p.WaitForExit();
Process p = new Process();
p.StartInfo.FileName = " cmd.exe " ;
p.StartInfo.UseShellExecute = false ;
p.StartInfo.RedirectStandardInput = true ;
p.StartInfo.RedirectStandardOutput = true ;
p.StartInfo.RedirectStandardError = true ;
p.StartInfo.CreateNoWindow = true ;
p.StartInfo.Arguments = " /c net share 共享的名称(例如test)=要开启共享的文件夹(例如c:\\testfolder) " ;
p.Start();
p.WaitForExit();
注意WaitForExit这个方法,开始的时候非常奇怪,就是程序启动后的第二次备份总不能成功,原来是我们开共享时没有等待net share 命令完全执行完就去执行net use这个共享文件夹,所以肯定不会成功了...
2:启动远程数据库的xpcmd
//
开启xpcmd
string sql = " EXEC sp_configure 'show advanced options', 1\r\n " +
" RECONFIGURE \r\n " +
" EXEC sp_configure 'xp_cmdshell', 1; \r\n " +
" RECONFIGURE \r\n " ; // 执行这个sql
3:执行net use命令引用主程序所在机器开启的共享文件夹
string sql = " EXEC sp_configure 'show advanced options', 1\r\n " +
" RECONFIGURE \r\n " +
" EXEC sp_configure 'xp_cmdshell', 1; \r\n " +
" RECONFIGURE \r\n " ; // 执行这个sql
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
string sql = "xp_cmdshell 'net use \\\\" + Dns.GetHostName() + "\\共享的名称(例如test)= 用户密码 /user:domain\\用户名 '; ";//执行这个sql
需要注意的就是这个Dns.GetHostName() ,我们用的是主机名来连接的,本来我们是要用内网ip的,但是机器的内网ip很不好获取,有的还没有内网ip,所以用的主机名,对于有防火墙的可能需要配置一下允许通过主机名来访问.
4:上面已经通过xp_cmdshell连接上了远程共享了,那么下面的备份还是还原就都简单了只要把以前的备份还原的路径换成现在的"\\主机名\共享目录名\备份或还原文件"即可.
例如备份的sql就是:
StringBuilder sql
=
new
StringBuilder();
// 备份到本地
sql.Append( " BACKUP DATABASE [ " );
sql.Append(要备份的数据库名称);
sql.Append( " ] to disk=' " );
sql.Append( " \\\\ " + Dns.GetHostName() + " \\共享名称 " );
sql.Append( " \\ " );
sql.Append(备份的文件名称);
sql.Append( " ' " );
执行这个sql即可.
// 备份到本地
sql.Append( " BACKUP DATABASE [ " );
sql.Append(要备份的数据库名称);
sql.Append( " ] to disk=' " );
sql.Append( " \\\\ " + Dns.GetHostName() + " \\共享名称 " );
sql.Append( " \\ " );
sql.Append(备份的文件名称);
sql.Append( " ' " );
5:最后不要忘了关闭共享目录和xp_cmdshell
//
关闭共享
Process p = new Process();
p.StartInfo.FileName = " cmd.exe " ;
p.StartInfo.UseShellExecute = false ;
p.StartInfo.RedirectStandardInput = true ;
p.StartInfo.RedirectStandardOutput = true ;
p.StartInfo.RedirectStandardError = true ;
p.StartInfo.CreateNoWindow = true ;
p.StartInfo.Arguments = " /c net share 共享名称 /delete /y " ;
p.Start();
p.WaitForExit();
Process p = new Process();
p.StartInfo.FileName = " cmd.exe " ;
p.StartInfo.UseShellExecute = false ;
p.StartInfo.RedirectStandardInput = true ;
p.StartInfo.RedirectStandardOutput = true ;
p.StartInfo.RedirectStandardError = true ;
p.StartInfo.CreateNoWindow = true ;
p.StartInfo.Arguments = " /c net share 共享名称 /delete /y " ;
p.Start();
p.WaitForExit();
这里要注意一下"/delete /y",因为执行这个delete命令时会提示输入y或n来确定一下,所以这样就直接通过提示了.
//
关闭xpcmd
string sqlcmd = " EXEC sp_configure 'show advanced options', 1; \r\n " +
" RECONFIGURE\r\n " +
" EXEC sp_configure 'xp_cmdshell', 0; \r\n " +
" RECONFIGURE \r\n " ; // 执行这个sql
string sqlcmd = " EXEC sp_configure 'show advanced options', 1; \r\n " +
" RECONFIGURE\r\n " +
" EXEC sp_configure 'xp_cmdshell', 0; \r\n " +
" RECONFIGURE \r\n " ; // 执行这个sql
ok.