Microsoft KB Archive/185125: Difference between revisions

From BetaArchive Wiki
(importing KB archive)
 
m (Text replacement - "&" to "&")
 
(4 intermediate revisions by the same user not shown)
Line 63: Line 63:
== MORE INFORMATION ==
== MORE INFORMATION ==


These code snippets are abbreviated from the ADO samples listed in the &quot;References&quot; section. Please use the full ADO samples if you want to build and run this code.<br />
These code snippets are abbreviated from the ADO samples listed in the "References" section. Please use the full ADO samples if you want to build and run this code.<br />
<br />
<br />


=== VBA in Visual Basic or Microsoft Access &amp; VBScript from ASP ===
=== VBA in Visual Basic or Microsoft Access & VBScript from ASP ===


<pre class="codesample">  Dim Conn1 As ADODB.Connection
<pre class="codesample">  Dim Conn1 As ADODB.Connection
Line 86: Line 86:




   sConnect= &quot;driver={sql server};&quot; &amp;amp; _
   sConnect= "driver={sql server};" & _




             &quot;server=server_name;&quot; &amp;amp; _
             "server=server_name;" & _
             &quot;Database=pubs;UID=uder_id;PWD=password;&quot;
             "Database=pubs;UID=uder_id;PWD=password;"




   sCreate = &quot;create proc sp_AdoTest( @InParam int, &quot; &amp;amp; _
   sCreate = "create proc sp_AdoTest( @InParam int, " & _




             &quot;@OutParam int OUTPUT ) &quot; &amp;amp; _
             "@OutParam int OUTPUT ) " & _
             &quot;as &quot; &amp;amp; _
             "as " & _
             &quot;select @OutParam = @InParam + 10 &quot; &amp;amp; _
             "select @OutParam = @InParam + 10 " & _
             &quot;SELECT * FROM Authors WHERE &quot;   &amp;amp; _
             "SELECT * FROM Authors WHERE "   & _
             &quot;State &lt;&gt; 'CA' &quot; &amp;amp; _
             "State <> 'CA' " & _
             &quot;return @OutParam +10&quot;
             "return @OutParam +10"




   sDrop  = &quot;if exists &quot; &amp;amp; _
   sDrop  = "if exists " & _




             &quot;(select * from sysobjects where &quot; &amp;amp; _
             "(select * from sysobjects where " & _
             &quot;id = object_id('dbo.sp_AdoTest') and &quot; &amp;amp; _
             "id = object_id('dbo.sp_AdoTest') and " & _
             &quot;sysstat &amp;amp; 0xf = 4)&quot; &amp;amp; _
             "sysstat & 0xf = 4)" & _
             &quot;drop procedure dbo.sp_AdoTest&quot;
             "drop procedure dbo.sp_AdoTest"




   sSP    = &quot;sp_Adotest&quot;
   sSP    = "sp_Adotest"




Line 122: Line 122:




   ' Drop procedure, if it exists &amp;amp; recreate it.
   ' Drop procedure, if it exists & recreate it.
   Set Rs1 = Conn1.Execute(sDrop, l, adCmdText)
   Set Rs1 = Conn1.Execute(sDrop, l, adCmdText)
   Set Rs1 = Nothing
   Set Rs1 = Nothing
Line 134: Line 134:
   Set Cmd1 = New ADODB.Command
   Set Cmd1 = New ADODB.Command
   Cmd1.ActiveConnection = Conn1
   Cmd1.ActiveConnection = Conn1
   Cmd1.CommandText = &quot;sp_AdoTest&quot;
   Cmd1.CommandText = "sp_AdoTest"
   Cmd1.CommandType = adCmdStoredProc
   Cmd1.CommandType = adCmdStoredProc
   Cmd1.Parameters.Refresh
   Cmd1.Parameters.Refresh
Line 149: Line 149:




   Debug.print vbTab &amp;amp; &quot;RetVal Param = &quot; &amp;amp; Cmd1.Parameters(0).Value
   Debug.print vbTab & "RetVal Param = " & Cmd1.Parameters(0).Value
   Debug.print vbTab &amp;amp; &quot;Input  Param = &quot; &amp;amp; Cmd1.Parameters(1).Value
   Debug.print vbTab & "Input  Param = " & Cmd1.Parameters(1).Value
   Debug.print vbTab &amp;amp; &quot;Output Param = &quot; &amp;amp; Cmd1.Parameters(2).Value
   Debug.print vbTab & "Output Param = " & Cmd1.Parameters(2).Value
                 </pre>
                 </pre>
For VBScript users, you would replace the Dim statements with equivalent CreateObject calls, such as:
For VBScript users, you would replace the Dim statements with equivalent CreateObject calls, such as:
<pre class="codesample">  Set conn1 = CreateObject( &quot;ADODB.Connection.1.5&quot; )
<pre class="codesample">  Set conn1 = CreateObject( "ADODB.Connection.1.5" )
                 </pre>
                 </pre>
As ADO version 1.x is not binary compatible, it is helpful to specify which version of ADO your script is referencing.
As ADO version 1.x is not binary compatible, it is helpful to specify which version of ADO your script is referencing.
=== C++ Using #import ===
=== C++ Using #import ===


<pre class="codesample">  #import &quot;C:\Program Files\Common Files\System\ado\msado15.dll&quot; \  
<pre class="codesample">  #import "C:\Program Files\Common Files\System\ado\msado15.dll" \  


   _variant_t  vtEmpty (DISP_E_PARAMNOTFOUND, VT_ERROR);
   _variant_t  vtEmpty (DISP_E_PARAMNOTFOUND, VT_ERROR);


           rename( &quot;EOF&quot;, &quot;adoEOF&quot; )
           rename( "EOF", "adoEOF" )




Line 172: Line 172:




   _bstr_t    bstrConnect( L&quot;driver={sql server};&quot;
   _bstr_t    bstrConnect( L"driver={sql server};"




                           L&quot;server=server_name;&quot;
                           L"server=server_name;"
                           L&quot;Database=pubs;UID=user_id;PWD=password;&quot; );
                           L"Database=pubs;UID=user_id;PWD=password;" );




   _bstr_t    bstrCreate ( L&quot;create proc sp_AdoTest( @InParam int, &quot;
   _bstr_t    bstrCreate ( L"create proc sp_AdoTest( @InParam int, "




                           L&quot;@OutParam int OUTPUT ) &quot;
                           L"@OutParam int OUTPUT ) "
                           L&quot;as &quot;
                           L"as "
                           L&quot;select @OutParam = @InParam + 10 &quot;
                           L"select @OutParam = @InParam + 10 "
                           L&quot;SELECT * FROM Authors WHERE &quot;
                           L"SELECT * FROM Authors WHERE "
                           L&quot;State &lt;&gt; 'CA' &quot;
                           L"State <> 'CA' "
                           L&quot;return @OutParam +10&quot; );
                           L"return @OutParam +10" );




   _bstr_t    bstrDrop  ( L&quot;if exists &quot;
   _bstr_t    bstrDrop  ( L"if exists "




                           L&quot;(select * from sysobjects where &quot;
                           L"(select * from sysobjects where "
                           L&quot;id = object_id('dbo.sp_AdoTest') and &quot;
                           L"id = object_id('dbo.sp_AdoTest') and "
                           L&quot;sysstat &amp;amp; 0xf = 4)&quot;
                           L"sysstat & 0xf = 4)"
                           L&quot;drop procedure dbo.sp_AdoTest&quot; );
                           L"drop procedure dbo.sp_AdoTest" );




   _bstr_t    bstrSP    ( L&quot;sp_Adotest&quot; );
   _bstr_t    bstrSP    ( L"sp_Adotest" );




Line 208: Line 208:
       // Establish connection.
       // Establish connection.
       Conn1.CreateInstance( __uuidof( ADODB::Connection ) );
       Conn1.CreateInstance( __uuidof( ADODB::Connection ) );
       Conn1-&gt;ConnectionString = bstrConnect;
       Conn1->ConnectionString = bstrConnect;
       Conn1-&gt;Open( bstrEmpty, bstrEmpty, bstrEmpty, -1 );
       Conn1->Open( bstrEmpty, bstrEmpty, bstrEmpty, -1 );




       // Drop procedure, if it exists &amp;amp; recreate it.
       // Drop procedure, if it exists & recreate it.
       Conn1-&gt;Execute( bstrDrop, &amp;amp;vtEmpty, ADODB::adCmdText);
       Conn1->Execute( bstrDrop, &vtEmpty, ADODB::adCmdText);
       Conn1-&gt;Execute( bstrCreate, &amp;amp;vtEmpty, ADODB::adCmdText);
       Conn1->Execute( bstrCreate, &vtEmpty, ADODB::adCmdText);




       // Open recordset.
       // Open recordset.
       Cmd1.CreateInstance( __uuidof( ADODB::Command ) );
       Cmd1.CreateInstance( __uuidof( ADODB::Command ) );
       Cmd1-&gt;ActiveConnection = Conn1;
       Cmd1->ActiveConnection = Conn1;
       Cmd1-&gt;CommandText      = bstrSP;
       Cmd1->CommandText      = bstrSP;
       Cmd1-&gt;CommandType      = ADODB::adCmdStoredProc;
       Cmd1->CommandType      = ADODB::adCmdStoredProc;




       Cmd1-&gt;Parameters-&gt;Refresh();
       Cmd1->Parameters->Refresh();
       Cmd1-&gt;Parameters-&gt;Item[ _variant_t( (long) 1 ) ]-&gt;Value =
       Cmd1->Parameters->Item[ _variant_t( (long) 1 ) ]->Value =
                                                   _variant_t( (long) 10 );
                                                   _variant_t( (long) 10 );




       Rs1 = Cmd1-&gt;Execute( &amp;amp;vtEmpty, &amp;amp;vtEmpty2,
       Rs1 = Cmd1->Execute( &vtEmpty, &vtEmpty2,
ADODB::adCmdUnknown );
ADODB::adCmdUnknown );




       // Process results from recordset, then close it.
       // Process results from recordset, then close it.
       Rs1-&gt;Close();
       Rs1->Close();




       // Get parameters.
       // Get parameters.
       TRACE( &quot;\tRetVal Param = %s&quot;,
       TRACE( "\tRetVal Param = %s",
               CrackStrVariant( (tagVARIANT)
               CrackStrVariant( (tagVARIANT)
                     Cmd1-&gt;Parameters-&gt;Item[ _variant_t( 0L ) ]-
                     Cmd1->Parameters->Item[ _variant_t( 0L ) ]-
&gt;Value ) );
>Value ) );
       TRACE( &quot;\tInput  Param = %s&quot;,
       TRACE( "\tInput  Param = %s",
               CrackStrVariant( (tagVARIANT)
               CrackStrVariant( (tagVARIANT)
                     Cmd1-&gt;Parameters-&gt;Item[ _variant_t( 1L ) ]-
                     Cmd1->Parameters->Item[ _variant_t( 1L ) ]-
&gt;Value ) );
>Value ) );
       TRACE( &quot;\tOutput Param = %s&quot;,
       TRACE( "\tOutput Param = %s",
               CrackStrVariant( (tagVARIANT)
               CrackStrVariant( (tagVARIANT)
                     Cmd1-&gt;Parameters-&gt;Item[ _variant_t( 2L ) ]-
                     Cmd1->Parameters->Item[ _variant_t( 2L ) ]-
&gt;Value ) );
>Value ) );




   }
   }
   catch( CException *e ) { e-&gt;Delete(); }
   catch( CException *e ) { e->Delete(); }
   catch(...)            {  }
   catch(...)            {  }
                 </pre>
                 </pre>
Line 274: Line 274:




               &quot;driver={sql server};&quot; +
               "driver={sql server};" +
               &quot;server=CharlotteTown;Database=pubs;UID=sa;PWD=;&quot;);
               "server=CharlotteTown;Database=pubs;UID=sa;PWD=;");




Line 281: Line 281:




               &quot;create proc sp_AdoTest( @InParam int, &quot; +
               "create proc sp_AdoTest( @InParam int, " +
               &quot;@OutParam int OUTPUT ) &quot; +
               "@OutParam int OUTPUT ) " +
               &quot;as &quot; +
               "as " +
               &quot;select @OutParam = @InParam + 10 &quot; +
               "select @OutParam = @InParam + 10 " +
               &quot;SELECT * FROM Authors WHERE &quot; +
               "SELECT * FROM Authors WHERE " +
               &quot;State &lt;&gt; 'CA' &quot; +
               "State <> 'CA' " +
               &quot;return @OutParam +10&quot; );
               "return @OutParam +10" );




Line 293: Line 293:




               &quot;if exists &quot; +
               "if exists " +
               &quot;(select * from sysobjects where &quot; +
               "(select * from sysobjects where " +
               &quot;id = object_id('dbo.sp_AdoTest') and &quot; +
               "id = object_id('dbo.sp_AdoTest') and " +
               &quot;sysstat &amp;amp; 0xf = 4)&quot; +
               "sysstat & 0xf = 4)" +
               &quot;drop procedure dbo.sp_AdoTest&quot; );
               "drop procedure dbo.sp_AdoTest" );




   String  bstrSP      = new String( &quot;sp_Adotest&quot; );
   String  bstrSP      = new String( "sp_Adotest" );




Line 313: Line 313:




       // Drop procedure, if it exists &amp;amp; recreate it.
       // Drop procedure, if it exists & recreate it.
       vtEmpty.noParam();
       vtEmpty.noParam();
       Conn1.Execute( bstrDrop, vtEmpty,
       Conn1.Execute( bstrDrop, vtEmpty,
Line 347: Line 347:
       // Get parameters (assumes you have a listbox named List1)
       // Get parameters (assumes you have a listbox named List1)
       v1.putInt( 0 );
       v1.putInt( 0 );
       List1.addItem( &quot;   RetVal Param = &quot; +
       List1.addItem( "   RetVal Param = " +
                         Cmd1.getParameters().getItem( v1 ).getValue() );
                         Cmd1.getParameters().getItem( v1 ).getValue() );
       v1.putInt( 1 );
       v1.putInt( 1 );
       List1.addItem( &quot;   Input  Param = &quot; +
       List1.addItem( "   Input  Param = " +
                         Cmd1.getParameters().getItem( v1 ).getValue() );
                         Cmd1.getParameters().getItem( v1 ).getValue() );
       v1.putInt( 2 );
       v1.putInt( 2 );
       List1.addItem( &quot;   Output Param = &quot; +
       List1.addItem( "   Output Param = " +
                         Cmd1.getParameters().getItem( v1 ).getValue() );
                         Cmd1.getParameters().getItem( v1 ).getValue() );
   }
   }

Latest revision as of 13:54, 21 July 2020

Article ID: 185125

Article Last Modified on 3/14/2005



APPLIES TO

  • Microsoft ActiveX Data Objects 1.0
  • Microsoft ActiveX Data Objects 1.5
  • Microsoft ActiveX Data Objects 2.0
  • Microsoft ActiveX Data Objects 2.1
  • Microsoft ActiveX Data Objects 2.5
  • Microsoft ActiveX Data Objects 2.6
  • Microsoft ActiveX Data Objects 2.7



This article was previously published under Q185125

SUMMARY

In order to open a stored procedure within ActiveX Data Objects (ADO), you must first open a Connection Object, then a Command Object, fill the Parameters Collection with one parameter in the collection for each parameter in the query, and then use the Command.Execute() method to open the ADO Recordset.

You may optionally use the Parameters.Refresh method to populate the Parameters Collection for the stored procedure. In addition, if the stored procedure is returning output or return parameters, you need to close the recordset before checking the value of the output parameters.

This is demonstrated in the code snippets below that deletes (if it already exists) and then creates a stored procedure, sp_adoTest, on a SQL Server that has input, output, and return parameters, as well as returning a recordset.

This article demonstrates how to perform this operation using VBA/VBScript, C++, and Java.

MORE INFORMATION

These code snippets are abbreviated from the ADO samples listed in the "References" section. Please use the full ADO samples if you want to build and run this code.

VBA in Visual Basic or Microsoft Access & VBScript from ASP

   Dim Conn1 As ADODB.Connection
   Dim Cmd1 As ADODB.Command
   Dim Rs1 As ADODB.Recordset


   Dim strTmp As String


   Dim Connect As String
   Dim Drop As String
   Dim Create As String
   Dim sp as string


   Dim i As Integer
   Dim l As Long


   sConnect= "driver={sql server};" & _


             "server=server_name;" & _
             "Database=pubs;UID=uder_id;PWD=password;"


   sCreate = "create proc sp_AdoTest( @InParam int, " & _


             "@OutParam int OUTPUT ) " & _
             "as "  & _
             "select @OutParam = @InParam + 10 " & _
             "SELECT * FROM Authors WHERE "   & _
             "State <> 'CA' "  & _
             "return @OutParam +10"


   sDrop   = "if exists "  & _


             "(select * from sysobjects where "  & _
             "id = object_id('dbo.sp_AdoTest') and " & _
             "sysstat & 0xf = 4)"  & _
             "drop procedure dbo.sp_AdoTest"


   sSP     = "sp_Adotest"


   ' Establish connection.
   Set Conn1 = New ADODB.Connection
   Conn1.ConnectionString = sConnect
   Conn1.Open


   ' Drop procedure, if it exists & recreate it.
   Set Rs1 = Conn1.Execute(sDrop, l, adCmdText)
   Set Rs1 = Nothing


   Set Rs1 = Conn1.Execute(sCreate, l, adCmdText)
   Set Rs1 = Nothing


   ' Open recordset.
   Set Cmd1 = New ADODB.Command
   Cmd1.ActiveConnection = Conn1
   Cmd1.CommandText = "sp_AdoTest"
   Cmd1.CommandType = adCmdStoredProc
   Cmd1.Parameters.Refresh
   Cmd1.Parameters(1).Value = 10
   Set Rs1 = Cmd1.Execute()


   ' Process results from recordset, then close it.
   RS1.Close
   Set Rs1 = Nothing


   ' Get parameters (assumes you have a list box named List1).


   Debug.print vbTab & "RetVal Param = " & Cmd1.Parameters(0).Value
   Debug.print vbTab & "Input  Param = " & Cmd1.Parameters(1).Value
   Debug.print vbTab & "Output Param = " & Cmd1.Parameters(2).Value
                

For VBScript users, you would replace the Dim statements with equivalent CreateObject calls, such as:

   Set conn1 = CreateObject( "ADODB.Connection.1.5" )
                

As ADO version 1.x is not binary compatible, it is helpful to specify which version of ADO your script is referencing.

C++ Using #import

   #import "C:\Program Files\Common Files\System\ado\msado15.dll" \ 

   _variant_t  vtEmpty (DISP_E_PARAMNOTFOUND, VT_ERROR);

           rename( "EOF", "adoEOF" )


   ...
   ADODB::_ConnectionPtr  Conn1;
   ADODB::_CommandPtr     Cmd1;
   ADODB::_RecordsetPtr   Rs1;


   _bstr_t    bstrConnect( L"driver={sql server};"


                           L"server=server_name;"
                           L"Database=pubs;UID=user_id;PWD=password;" );


   _bstr_t    bstrCreate ( L"create proc sp_AdoTest( @InParam int, "


                           L"@OutParam int OUTPUT ) "
                           L"as "
                           L"select @OutParam = @InParam + 10 "
                           L"SELECT * FROM Authors WHERE "
                           L"State <> 'CA' "
                           L"return @OutParam +10" );


   _bstr_t    bstrDrop   ( L"if exists "


                           L"(select * from sysobjects where "
                           L"id = object_id('dbo.sp_AdoTest') and "
                           L"sysstat & 0xf = 4)"
                           L"drop procedure dbo.sp_AdoTest" );


   _bstr_t    bstrSP     ( L"sp_Adotest" );


   try
   {


       // Establish connection.
       Conn1.CreateInstance( __uuidof( ADODB::Connection ) );
       Conn1->ConnectionString = bstrConnect;
       Conn1->Open( bstrEmpty, bstrEmpty, bstrEmpty, -1 );


       // Drop procedure, if it exists & recreate it.
       Conn1->Execute( bstrDrop, &vtEmpty, ADODB::adCmdText);
       Conn1->Execute( bstrCreate, &vtEmpty, ADODB::adCmdText);


       // Open recordset.
       Cmd1.CreateInstance( __uuidof( ADODB::Command ) );
       Cmd1->ActiveConnection = Conn1;
       Cmd1->CommandText      = bstrSP;
       Cmd1->CommandType      = ADODB::adCmdStoredProc;


       Cmd1->Parameters->Refresh();
       Cmd1->Parameters->Item[ _variant_t( (long) 1 ) ]->Value =
                                                  _variant_t( (long) 10 );


       Rs1 = Cmd1->Execute( &vtEmpty, &vtEmpty2,
ADODB::adCmdUnknown );


       // Process results from recordset, then close it.
       Rs1->Close();


       // Get parameters.
       TRACE( "\tRetVal Param = %s",
              CrackStrVariant( (tagVARIANT)
                    Cmd1->Parameters->Item[ _variant_t( 0L ) ]-
>Value ) );
       TRACE( "\tInput  Param = %s",
              CrackStrVariant( (tagVARIANT)
                    Cmd1->Parameters->Item[ _variant_t( 1L ) ]-
>Value ) );
       TRACE( "\tOutput Param = %s",
              CrackStrVariant( (tagVARIANT)
                    Cmd1->Parameters->Item[ _variant_t( 2L ) ]-
>Value ) );


   }
   catch( CException *e ) { e->Delete(); }
   catch(...)             {  }
                

For a demonstration of how to use a Parameterized Query either with classes generated by the MFC ClassWizard, or using straight COM programming, please see the ADOVC sample referenced in the REFERENCES section.

CrackStrVariant is a function that stuffs the contents of a Variant into a CString (if possible) and is demonstrated in the Adovc.exe sample referenced below.

Java

   msado15._Connection  Conn1   = new msado15.Connection();
   msado15._Command     Cmd1    = null;
   msado15._Recordset   Rs1     = new msado15.Recordset();


   Variant              v1 = new Variant();
   Variant              v2 = new Variant();


   String  bstrConnect = new String(


               "driver={sql server};" +
               "server=CharlotteTown;Database=pubs;UID=sa;PWD=;");


   String  bstrCreate  = new String(


               "create proc sp_AdoTest( @InParam int, " +
               "@OutParam int OUTPUT ) " +
               "as " +
               "select @OutParam = @InParam + 10 " +
               "SELECT * FROM Authors WHERE " +
               "State <> 'CA' " +
               "return @OutParam +10" );


   String  bstrDrop    = new String(


               "if exists " +
               "(select * from sysobjects where " +
               "id = object_id('dbo.sp_AdoTest') and " +
               "sysstat & 0xf = 4)" +
               "drop procedure dbo.sp_AdoTest" );


   String  bstrSP      = new String( "sp_Adotest" );


   // Trap any error/exception.
   try
   {


       // Establish connection.
       Conn1.putConnectionString( bstrConnect );
       Conn1.Open( bstrEmpty, bstrEmpty, bstrEmpty, -1 );


       // Drop procedure, if it exists & recreate it.
       vtEmpty.noParam();
       Conn1.Execute( bstrDrop, vtEmpty,
                                       msado15.CommandTypeEnum.adCmdText);
       vtEmpty.noParam();
       Conn1.Execute( bstrCreate, vtEmpty,
                                       msado15.CommandTypeEnum.adCmdText);


      // Open recordset.
       Cmd1= new msado15.Command();
       Cmd1.putActiveConnection( Conn1 );
       Cmd1.putCommandText     ( bstrSP );
       Cmd1.putCommandType     (msado15.CommandTypeEnum.adCmdStoredProc);


       Cmd1.getParameters().Refresh();
       v1.putInt( 1 );
       v2.putInt( 10 );
       Cmd1.getParameters().getItem( v1 ).putValue( v2 );


       vtEmpty.noParam();
       vtEmpty2.noParam();
       Rs1 = Cmd1.Execute( vtEmpty, vtEmpty2,
                                  msado15.CommandTypeEnum.adCmdUnknown );


       // Process results from recordset, then close it.
       Rs1.Close();


       // Get parameters (assumes you have a listbox named List1)
       v1.putInt( 0 );
       List1.addItem( "    RetVal Param = " +
                         Cmd1.getParameters().getItem( v1 ).getValue() );
       v1.putInt( 1 );
       List1.addItem( "    Input  Param = " +
                         Cmd1.getParameters().getItem( v1 ).getValue() );
       v1.putInt( 2 );
       List1.addItem( "    Output Param = " +
                         Cmd1.getParameters().getItem( v1 ).getValue() );
   }
   // Catch Blocks
   catch (com.ms.com.ComFailException e) { }
   catch(Exception e)                    { }
                

REFERENCES

For additional information, please see the following articles in the Microsoft Knowledge Base:

172403 SAMPLE: Adovb.exe Demonstrates How to Use ADO with Visual Basic

220152 FILE: Adovc.exe Demonstrates How To Use ADO with Visual C++

Keywords: kbhowto kbdatabase kbmdacnosweep kbcode kbarttypeinf KB185125