I'm trying to run a report that execute some SQL queries in NAV 2015
If I run the report manually it's working perfectly, but when I set it into the Task Scheduler it give error as it has an automation that is trying to load in the client.
I've changed the CREATE parameters to (FALSE, FALSE) instead of (FALSE, TRUE) so it runs in Server instead of Client, but when I try to compile it will give this error:
Translation: Cannot create an automation object "sqlConnection" in NAV Server. You must create it in Client.
But if I create it in client CREATE(FALSE, TRUE) it will give error:
Translation: NAV Server was trying to return a Client call to create an automation object. Call returns from Client are not allowed in NAV Server.
This is the code: (Looping Company table)
IF (STRPOS(LOWERCASE(Company.Name), 'prueba') = 0) AND (STRPOS(LOWERCASE(Company.Name), 'test') = 0) AND (STRPOS(LOWERCASE(Company.Name), 'uat') = 0) AND (STRPOS(LOWERCASE(Company.Name), 'prova') = 0) THEN BEGIN
recWasteHeader.CHANGECOMPANY(Company.Name);
IF recWasteHeader.COUNT > 0 THEN BEGIN
recWasteLine.SETRANGE("Document Type", 4);
recWasteLine.SETRANGE("Business Type", 2);
recWasteLine.SETFILTER("Sub Contract No.", '<>%1', '*NUL*');
IF recWasteLine.FINDSET THEN BEGIN
IF ISCLEAR(sqlConnection) THEN
CREATE(sqlConnection, FALSE, FALSE);
sqlConnection.Open(ConnectionString);
IF ISCLEAR(sqlCommand) THEN
CREATE(sqlCommand, FALSE, FALSE);
sqlCommand.ActiveConnection := sqlConnection;
sqlCommand.CommandText := 'DELETE FROM [Noc Services Price] WHERE Empresa=' + q + Company.Name + q;
sqlCommand.CommandType := 1;
sqlCommand.Execute;
REPEAT
querydata := STRSUBSTNO(dataset, Company.Name, recWasteLine."Document No.", recWasteLine."Line No.", recWasteLine.Amount);
sqlCommand.CommandText := 'INSERT INTO [Noc Services Price] (Empresa, Contracte, [Linea contracte], [PREU ACTUAL]) VALUES ( ' + querydata + ');';
sqlCommand.Execute;
UNTIL recWasteLine.NEXT = 0;
sqlConnection.Close;
END;
END;
END;
I also can't find the dotnet System.Data.SqlClient
Related
I'm trying to mock a method written with sqlboiler but I'm having massive trouble building the mock-query.
The model I'm trying to mock looks like this:
type Course struct {
ID int, Name string, Description null.String, EnrollKey string, ForumID int,
CreatedAt null.Time, UpdatedAt null.Time, DeletedAt null.Time,
R *courseR, L courseL
}
For simplicity I want to test the GetCourse-method
func (p *PublicController) GetCourse(id int) (*models.Course, error) {
c, err := models.FindCourse(context.Background(), p.Database, id)
if err != nil {
return nil, err
}
return c, nil
}
with this test
func TestGetCourse(t *testing.T) {
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("an error '%s' was not expected", err)
}
oldDB := boil.GetDB()
defer func() {
db.Close()
boil.SetDB(oldDB)
}()
boil.SetDB(db)
ctrl := &PublicController{db}
rows := sqlmock.NewRows([]string{"ID", "Name", "Description", "EnrollKey", "ForumID"}).AddRow(42, "Testkurs", "12345", 33)
query := regexp.QuoteMeta("SELECT ID, Name, Description, EnrollKey, ForumID FROM courses WHERE ID = ?")
//mockQuery := regexp.QuoteMeta("SELECT * FROM `courses` WHERE (`course AND (`courses`.deleted_at is null) LIMIT 1;")
mock.ExpectQuery(query).WithArgs(42).WillReturnRows(rows)
course, err := ctrl.GetCourse(42)
assert.NotNil(t, course)
assert.NoError(t, err)
}
But running this test only returns
Query: could not match actual sql: "select * from course where id=? and deleted_at is null" with expected regexp "SELECT ID, Name, Description, EnrollKey, ForumID FROM courses WHERE ID = ?"
bind failed to execute query
And I can't really find out how to construct it correctly.
How do I correctly mock the sqlboiler-query for running unit tests?
UPDATE
I managed to solve this by using different parameters in AddRow()
.AddRow(c.ID, c.Name, null.String{}, c.EnrollKey, c.ForumID)
and building the query differently
query := regexp.QuoteMeta("select * from `course` where `id`=? and `deleted_at` is null")
Now my issue is that in contrast to this method the others have a very large complexity in comparison with a large amount of complex queries (mainly insert-operations). From my understanding, sqlboiler-tests needs to mimic every single interaction made with the database.
How do I extract the necessary queries for the large amount of database interactions? I solved my problem by just using the "actual sql-query" instead of the previously used one but I'm afraid this procedure is the opposite of efficient testing.
I've got this line of SQL query to check the validity of a username password :
if exists (select * from Acc where username = :un and userpassword = HASHBYTES('SHA2_256', :pw)) select 1 else select 0
It works correctly when executed directly in SQL Server Management studio but when I bind values and query from Qt it won't work.
What am I doing wrong? I'd appreciate any help. I'll paste the complete code section in Qt below :
q->prepare("if exists (select * from Acc where username = :un and userpassword = HASHBYTES('SHA2_256', :pw)) select 1 else select 0");
q->bindValue(":un", un);
q->bindValue(":pw", pw);
if (q->exec())
{
q->next();
if (q->value(0).toInt() == 0)
{
QMessageBox::critical(this, "", "User not found", QMessageBox::Ok);
}
else
{
//execute form . . .
}
How can I release a Variable that is being used by the WebService.
I'm using this form:
HttpPrincipal.WSDLLocation: = FrmPrincipal.edtWS.Text;
HttpPrincipal.Service: = 'CADServicesService';
HttpPrincipal.Port := 'CADServices';
Trinity: = HttpPrincipal as CADServices;
At the moment when I will close the Form appears an error, and discovered that when I declare this part:
Trinity: = HttpPrincipal as CADServices;
I think it is getting stuck in memory.
The error is the following:
"Invalid Pointer"
The error happens when you close the form, does not have any event in the OnClose or OnDestroy form.
Descriptions:
Trinity : CADServices,
HttpPrincipal is a THTTPRIO,
CADServices is my Unit containing all procedures / functions from WebService.
Instead of using the designtime component try to create HTTPRIO at runtime:
function GetCadServices(Addr : String): CadServices;
const
defSvc = 'CADServicesService';
defPrt = 'CADServices';
var
RIO: THTTPRIO;
begin
Result := nil;
RIO := THTTPRIO.Create(nil)
try
Result := (RIO as CadServices);
RIO.WSDLLocation := Addr;
RIO.Service := defSvc;
RIO.Port := defPrt;
finally
if (Result = nil) then
RIO.Free;
end;
end;
Usage:
Trinity := GetCadServices(FrmPrincipal.edtWS.Text);
If you imported the WSDL with the WSDL importer this code is automatically generated for you (look in the CadServices1 unit)
Right now i have a function that runs a query, using ADO, and returns a recordset:
Recordset Execute(Connection connection, String commandText)
{
//[pseudo-code]
Recordset rs = new Recordset();
rs.CursorLocation = adUseClient;
rs.CursorType = adOpenForwardOnly;
rs.Open(commandText, connection,
adOpenForwardOnly, //CursorType; the default
adLockReadOnly, //LockType
adCmdText);
return rs;
}
And this is fine. It runs synchronously, and returns the recordset of a query.
Now i want a similar version, that shows a ProgressDialog, providing the user with the ability to cancel a long-running query:
Recordset Execute(HWND parenthWnd, String caption, Connection connection, String commandText)
{
//[pseudo-code]
//Construct a progressDialog and show it
IProgressDialog pd = new ProgressDialog();
pd.SetTitle(caption); //e.g. "Annual Funding Report"
pd.SetCancelMsg("Please wait while the operation is cancelled");
pd.StartProgressDialog(parenthWnd, null, PROGDLG_MODAL | PROGDLG_NOTIME | PROGDLG_NOMINIMIZE, null);
pd.SetLine(1, "Querying server", False, null);
try
{
//Query the server
Recordset rs = new Recordset();
rs.Open(commandText, connection,
adOpenForwardOnly, //CursorType
adLockReadOnly, //LockType
adCmdText | adAsyncExecute);
while (rs.State and (adStateConnecting+adStateExecuting+adStateFetching) <> 0)
{
if pd.HasUserCancelled()
throw new EUserCancelledOperationException();
Sleep(100);
};
finally
{
//Hide and destroy the progress dialog
pd.StopProgressDialog();
pd = null;
}
//Now we have our results for the client
return rs;
}
The way to check if the user has cancelled the operation is to periodically ask the progress dialog if the user as pressed the cancel button:
pd.HasUserCancelled(); //returns true if user has clicked Cancel
Now i'm faced with how to periodically check if the user has cancelled (and to know if the query has completed, or an error has happened), and to be a good programmer and do it without polling.
The only way to know that an error has happened is to have a handler on the Recordset's FetchCompleteEvent:
pError
An Error object. It describes the error that occurred if the value of adStatus is adStatusErrorsOccurred; otherwise it is not set.
adStatus
An EventStatusEnum status value. When this event is called, this parameter is set to adStatusOK if the operation that caused the event was successfull, or to adStatusErrorsOccurred if the operation failed.
Before this event returns, set this parameter to adStatusUnwantedEvent to prevent subsequent notifications.
pRecordset
A Recordset object. The object for which the records were retrieved.
So this would imply that i'm going to have to have my function construct a helper object, so i can have a FetchComplete handler. But then i have to prevent my synchronous function from returning right away. And then we get into MsgWaitForSingleObject, which is notoriously difficult to use correctly.
So i'm asking for assistance, or canned code.
i should be more explicit: i'm looking for an implementation of function with this method signature:
Recordset ExecuteWithCancelOption(Connection connection, String commandText)
that shows a dialog with a cancel button on it.
The challenge is that the function must now create whatever is required to achieve that. If that involves a hidden form, that has a timer on it, etc - okay.
But i'm looking for a synchronous function that displays a Cancel button.
And the function is going to be a near (or exact) drop-in replacement for
Recordset Execute(Connection connection, String commandText)
Given practical considerations on Windows, i would need to supply the function with a parent window handle that it will parent its dialog to:
Recordset ExecuteWithCancelOption(HWND parentHwnd, Connection connection, String commandText)
And given that this is going to be a reusable function, i'll let the caller provide the text that will be displayed:
Recordset ExecuteWithCancelOption(HWND parenthWnd, String caption, Connection connection, String commandText)
And given that these are both class functions in my TADOHelper class, i can give them the same name, and have them be overloads of one another:
Recordset Execute(HWND parenthWnd, String caption, Connection connection, String commandText)
i would think in languages other than Delphi, anonymous delegates are helpful. But i'm still terrified of having to deal with MsgWaitForMultipleObjects.
Progress informations and gracefully cancelling a query may not be available in every database engine. They need database support, both on the server and the client side. For example Oracle allows cancelling a query, yet has no "on progress" information but reading the V$SESSION_LONGOPS view. Sure, you can kill the session, but it will rollback the whole of it, not just cancel a give query execution.
Usually if the database supports this kind of features, the query is run in a separate thread that will wait for the result. That way the main thread can still get user input or read and display progress information (unless returned in some kind of callback). If the user cancels the query then the appropriate call is issued to stop the operation, allowing the query thread to return, usually the thread will receive a status code that will tell what's happened.
Be aware of how ADO implements async operations: http://msdn.microsoft.com/en-us/library/ms681467(VS.85).aspx
There's also a FetchProgress() event that could help you if you don't want to go the thread way (and even then to cancel a the query, if possible)
In order to make GUI to respond to button clicks you should return control to the message loop of the window. While loop while (rs.State and (adStateConnecting+adStateExecuting+adStateFetching) <> 0) does not return control back to the message loop thus blocking GUI.
Below is an excerpt from a working Delphi code that uses asyncronous ADO queries. This code does not allow for non-modal fetching of data, but ensures that the main form is repainted during data fetch and also allows cancelling the query.
Asynchronous execution and fetching is achieved by setting:
FOpeningDataSet.ExecuteOptions := [eoAsyncExecute, eoAsyncFetchNonBlocking];
execution of query is cancelled by calling
DataSet.Recordset.Cancel;
in FetchProgress event.
Any TADODataSet shall be opened via the method:
OpenDataSetInBackground(DataSourceData.DataSet as TADODataSet);
Supporting code in the main form:
procedure TOperatorForm.OpenDataSetInBackground(DataSet: TADODataSet);
begin
if DataSet.Active then Exit;
FOpeningDataSet := DataSet;
if not FAsyncDataFetch then
begin
FOpeningDataSet.Open;
Exit;
end;
FFetchCancel := False;
FExecuteOptions := FOpeningDataSet.ExecuteOptions;
FFetchProgress := FOpeningDataSet.OnFetchProgress;
FFetchComplete := FOpeningDataSet.OnFetchComplete;
FRecordsetCreate := FOpeningDataSet.OnRecordsetCreate;
FAfterScroll := FOpeningDataSet.AfterScroll;
FOpeningDataSet.ExecuteOptions := [eoAsyncExecute, eoAsyncFetchNonBlocking];
FOpeningDataSet.OnFetchProgress := DataSetFetchProgress;
FOpeningDataSet.OnFetchComplete := DataSetFetchComplete;
FOpeningDataSet.OnRecordsetCreate := DataSetRecordsetCreate;
FOpeningDataSet.AfterScroll := DataSetAfterScroll;
FOpeningDataSet.CursorLocation := clUseClient;
FOpeningDataSet.DisableControls;
try
DataSetProgressForm.Left := Left + (Width - DataSetProgressForm.Width) div 2;
DataSetProgressForm.Top := Top + (Height - DataSetProgressForm.Height) div 2;
DataSetProgressForm.cxButton1.OnClick := DataSetProgressClick;
DataSetProgressForm.cxButton1.Visible := FShowProgressCancelButton;
FOpeningDataSet.Open;
DataSetProgressForm.ShowModal;
finally
FOpeningDataSet.EnableControls;
FOpeningDataSet.ExecuteOptions := FExecuteOptions;
FOpeningDataSet.OnFetchProgress := FFetchProgress;
FOpeningDataSet.OnFetchComplete := FFetchComplete;
FOpeningDataSet.OnRecordsetCreate := FRecordsetCreate;
FOpeningDataSet.AfterScroll := FAfterScroll;
end;
end;
procedure TOperatorForm.DataSetProgressClick(Sender: TObject);
begin
FFetchCancel := True;
end;
procedure TOperatorForm.DataSetFetchProgress(DataSet: TCustomADODataSet; Progress, MaxProgress: Integer; var EventStatus: TEventStatus);
begin
if FFetchCancel then
DataSet.Recordset.Cancel;
end;
procedure TOperatorForm.DataSetFetchComplete(DataSet: TCustomADODataSet; const Error: Error; var EventStatus: TEventStatus);
begin
PostMessage(DataSetProgressForm.Handle, WM_CLOSE, 0, 0);
MessageBeep(MB_ICONEXCLAMATION);
end;
procedure TOperatorForm.DataSetFetchComplete(DataSet: TCustomADODataSet; const Error: Error; var EventStatus: TEventStatus);
begin
PostMessage(DataSetProgressForm.Handle, WM_CLOSE, 0, 0);
MessageBeep(MB_ICONEXCLAMATION);
end;
procedure TOperatorForm.DataSetRecordsetCreate(DataSet: TCustomADODataSet; const Recordset: _Recordset);
begin
if Assigned(FRecordsetCreate) then FRecordsetCreate(DataSet, Recordset);
end;
procedure TOperatorForm.DataSetAfterScroll(DataSet: TDataSet);
begin
// From TBetterADODataSet 4.04
// Ole Willy Tuv's fix 03-10-00 for missing first record
with TADODataSet(DataSet) do
begin
if (eoAsyncFetchNonBlocking in ExecuteOptions) and
(Bof or Eof) and
(CursorLocation = clUseClient) and
(stFetching in RecordSetState) then
begin
if Recordset.RecordCount > 0 then
if Bof then
Recordset.MoveFirst
else if Eof then
Recordset.MoveLast;
CursorPosChanged;
Resync([]);
end;
end;
if Assigned(FAfterScroll) then
FAfterScroll(DataSet);
end;
Progress form:
unit uDataSetProgressForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ExtCtrls, StdCtrls;
type
TDataSetProgressForm = class(TForm)
AnimateProgress: TAnimate;
Label1: TLabel;
Bevel1: TBevel;
Bevel2: TBevel;
Button1: TButton;
Shape1: TShape;
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure FormHide(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
DataSetProgressForm: TDataSetProgressForm;
implementation
{$R *.dfm}
{$R servertimeout.res} // contains IDR_SERVAVI animation resource
procedure TDataSetProgressForm.FormCreate(Sender: TObject);
begin
AnimateProgress.ResName := 'IDR_SERVAVI';
end;
procedure TDataSetProgressForm.FormShow(Sender: TObject);
begin
AnimateProgress.Active := True;
end;
procedure TDataSetProgressForm.FormHide(Sender: TObject);
begin
AnimateProgress.Active := False;
end;
end.
and dfm
object DataSetProgressForm: TDataSetProgressForm
Left = 590
Top = 497
BorderStyle = bsNone
ClientHeight = 104
ClientWidth = 205
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
FormStyle = fsStayOnTop
OldCreateOrder = False
Position = poDefaultSizeOnly
OnCreate = FormCreate
OnHide = FormHide
OnShow = FormShow
DesignSize = (
205
104)
PixelsPerInch = 96
TextHeight = 13
object Bevel1: TBevel
Left = 0
Top = 0
Width = 205
Height = 104
Align = alClient
Style = bsRaised
end
object Bevel2: TBevel
Left = 12
Top = 12
Width = 181
Height = 80
Anchors = [akLeft, akTop, akRight, akBottom]
end
object Shape1: TShape
Left = 1
Top = 1
Width = 203
Height = 102
Anchors = [akLeft, akTop, akRight, akBottom]
Brush.Style = bsClear
Pen.Color = clWindowFrame
end
object AnimateProgress: TAnimate
Left = 25
Top = 23
Width = 32
Height = 32
end
object Label1: TLabel
Left = 70
Top = 31
Width = 106
Height = 17
Hint = 'Selecting data...'
Caption = 'Selecting data...'
TabOrder = 1
end
object Button1: TButton
Left = 63
Top = 64
Width = 80
Height = 23
Caption = 'Cancel'
Default = True
TabOrder = 2
end
end
If it is Delphi you can drop a TTimer component in and use that to check if HasUserCancelled value is True. I don't have Delphi in front of me so I'd have to post an example later.
Edit:
Here's an example of a TTimer OnTimer event that checks the current time and the lastactivity time to decide what to do with the forms if the program has been left "Up":
procedure TForm_Main.Timer1Timer(Sender: TObject);
begin
// return to opening screen if no activity for a while:
if Now - LastActivity > TimeOut
then
begin
Form_Select.SBtn_Defendant.Down:= False;
Form_Select.SBtn_Officer.Down:= False;
Form_Select.SBtn_Attorney.Down:= False;
Form_Main.ModalResult:= mrCancel;
Exit;
end;
Form_Main.Caption:= FormatDateTime('dddd mmmm d, yyyy h:nn:ss AM/PM', Now);
end;
Using the SQL Server Reporting Services Web Service, how can I determine the permissions of a particular domain user for a particular report? The user in question is not the user that is accessing the Web Service.
I am accessing the Web Service using a domain service account (lets say MYDOMAIN\SSRSAdmin) that has full permissions in SSRS. I would like to programmatically find the permissions of a domain user (lets say MYDOMAIN\JimBob) for a particular report.
The GetPermissions() method on the Web Service will return a list of permissions that the current user has (MYDOMAIN\SSRSAdmin), but that is not what I'm looking for. How can I get this same list of permissions for MYDOMAIN\JimBob? I will not have the user's domain password, so using their credentials to call the GetPermissions() method is not an option. I am however accessing this from an account that has full permissions, so I would think that theoretically the information should be available to it.
SSRS gets the NT groups from the users' NT login token. This is why when you are added to a new group, you are expected to log out and back in. The same applies to most Windows checks (SQL Server, shares, NTFS etc).
If you know the NT group(s)...
You can query the ReportServer database directly. I've lifted this almost directly out of one of our reports which we use to check folder security (C.Type = 1). Filter on U.UserName.
SELECT
R.RoleName,
U.UserName,
C.Path
FROM
ReportServer.dbo.Catalog C WITH (NOLOCK) --Parent
JOIN
ReportServer.dbo.Policies P WITH (NOLOCK) ON C.PolicyID = P.PolicyID
JOIN
ReportServer.dbo.PolicyUserRole PUR WITH (NOLOCK) ON P.PolicyID = PUR.PolicyID
JOIN
ReportServer.dbo.Users U WITH (NOLOCK) ON PUR.UserID = U.UserID
JOIN
ReportServer.dbo.Roles R WITH (NOLOCK) ON PUR.RoleID = R.RoleID
WHERE
C.Type = 1
look into "GetPolicies Method" you can see at the following link.
http://msdn.microsoft.com/en-us/library/reportservice2010.reportingservice2010.getpolicies.aspx
Hopefully this will get you started. I use it when copying Folder structure, and Reports from an old server to a new server when I want to 'migrate' my SSRS items from the Source to the Destination Server. It is a a Method to Get the Security Policies for an item on one server, and then set the Security Policies for an identical item on another server, after I have copied the item from the Source Server to the Destination Server. You have to set your own Source and Destination Server Names.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Web.Services.Protocols; //<=== required for SoapException
namespace SSRS_WebServices_Utility
{
internal static class TEST
{
internal static void GetPoliciesForAnItem_from_Source_ThenSetThePolicyForTheItem_on_Destination(string itemPath)
{
string sSourceServer = "SOURCE-ServerName";
Source_ReportService2010.ReportingService2010 sourceRS = new Source_ReportService2010.ReportingService2010();
sourceRS.Credentials = System.Net.CredentialCache.DefaultCredentials;
sourceRS.Url = #"http://" + sSourceServer + "/reportserver/reportservice2010.asmx";
string sDestinationServer = "DESTINATION-ServerName";
Destination_ReportService2010.ReportingService2010 DestinationRS = new Destination_ReportService2010.ReportingService2010();
DestinationRS.Credentials = System.Net.CredentialCache.DefaultCredentials;
DestinationRS.Url = #"http://" + sDestinationServer + "/reportserver/reportservice2010.asmx";
Boolean val = true;
Source_ReportService2010.Policy[] curPolicy = null;
Destination_ReportService2010.Policy[] newPolicy = null;
try
{
curPolicy = new Source_ReportService2010.Policy[1];
curPolicy = sourceRS.GetPolicies(itemPath, out val); //e.g. of itemPath: "/B2W/001_OLD_PuertoRicoReport"
//DestinationRS.SetPolicies(itemPath, newPolicy);
int iCounter = 0;
//int iMax = curPolicy.Length;
newPolicy = new Destination_ReportService2010.Policy[curPolicy.Length];
foreach (Source_ReportService2010.Policy p in curPolicy)
{
//create the Policy
Destination_ReportService2010.Policy pNew = new Destination_ReportService2010.Policy();
pNew.GroupUserName = p.GroupUserName;
pNew.GroupUserName = p.GroupUserName;
Destination_ReportService2010.Role rNew = new Destination_ReportService2010.Role();
rNew.Description = p.Roles[0].Description;
rNew.Name = p.Roles[0].Name;
//create the Role, which is part of the Policy
pNew.Roles = new Destination_ReportService2010.Role[1];
pNew.Roles[0]=rNew;
newPolicy[iCounter] = pNew;
iCounter += 1;
}
DestinationRS.SetPolicies(itemPath, newPolicy);
Debug.Print("whatever");
}
catch (SoapException ex)
{
Debug.Print("SoapException: " + ex.Message);
}
catch (Exception Ex)
{
Debug.Print("NON-SoapException: " + Ex.Message);
}
finally
{
if (sourceRS != null)
sourceRS.Dispose();
if (DestinationRS != null)
DestinationRS.Dispose();
}
}
}
}
To invoke it use the following:
TEST.GetPoliciesForAnItem_from_Source_ThenSetThePolicyForTheItem_on_Destination("/FolderName/ReportName");
Where you have to put your own SSRS Folder Name and Report Name, i.e. the Path to the item.
In fact I use a method that loops through all the items in the Destination folder that then calls the method like this:
internal static void CopyTheSecurityPolicyFromSourceToDestinationForAllItems_2010()
{
string sDestinationServer = "DESTINATION-ServerName";
Destination_ReportService2010.ReportingService2010 DestinationRS = new Destination_ReportService2010.ReportingService2010();
DestinationRS.Credentials = System.Net.CredentialCache.DefaultCredentials;
DestinationRS.Url = #"http://" + sDestinationServer + "/reportserver/reportservice2010.asmx";
// Return a list of catalog items in the report server database
Destination_ReportService2010.CatalogItem[] items = DestinationRS.ListChildren("/", true);
// For each FOLDER, debug Print some properties
foreach (Destination_ReportService2010.CatalogItem ci in items)
{
{
Debug.Print("START----------------------------------------------------");
Debug.Print("Object Name: " + ci.Name);
Debug.Print("Object Type: " + ci.TypeName);
Debug.Print("Object Path: " + ci.Path);
Debug.Print("Object Description: " + ci.Description);
Debug.Print("Object ID: " + ci.ID);
Debug.Print("END----------------------------------------------------");
try
{
GetPoliciesForAnItem_from_Source_ThenSetThePolicyForTheItem_on_Destination(ci.Path);
}
catch (SoapException e)
{
Debug.Print("SoapException START----------------------------------------------------");
Debug.Print(e.Detail.InnerXml);
Debug.Print("SoapException END----------------------------------------------------");
}
catch (Exception ex)
{
Debug.Print("ERROR START----------------------------------------------------");
Debug.Print(ex.GetType().FullName);
Debug.Print(ex.Message);
Debug.Print("ERROR END----------------------------------------------------");
}
}
}
}